【发布时间】:2017-08-22 21:27:19
【问题描述】:
我有一个 XML 模式,我想将 RootNode 替换为在 RootNode 复杂类型中找到的元素。
例如,下面的预期结果是将<xs:element name="RootNode" ...> 替换为<xs:element name="real_node" type="RealNode"/> 并删除<xs:complexType name="RootNode"> 的整个节点。
XML 架构:
<xs:schema xmlns="test" xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="test" elementFormDefault="qualified">
<xs:element name="RootNode" type="RootNode"/>
<xs:complexType name="RootNode">
<xs:sequence>
<xs:element name="real_node" type="RealNode"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="RealNode">
<xs:annotation>
<xs:documentation source="Name" xml:lang="EN">TestName</xs:documentation>
<xs:documentation source="Type" xml:lang="EN">TestType</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:element name="Elem2" type="Type2" minOccurs="1">
<xs:annotation>
<xs:documentation source="Name3" xml:lang="EN">TestName3</xs:documentation>
<xs:documentation source="Type3" xml:lang="EN">TestType3</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="Elem4" type="Type4" maxOccurs="99" />
</xs:sequence>
</xs:complexType>
<xs:simpleType name="Type2">
<xs:restriction base="xs:string">
<xs:pattern value="[A-Z]{9,9}"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="Type4">
<xs:annotation>
<xs:documentation source="Name5" xml:lang="EN">TestName5</xs:documentation>
<xs:documentation source="Type5" xml:lang="EN">TestType5</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:string">
<xs:pattern value="[A-Z]{7,9}"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>
预期结果:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns="test" xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="test" elementFormDefault="qualified">
<xs:element name="real_node" type="RealNode"/>
<xs:complexType name="RealNode">
<xs:annotation>
<xs:documentation source="Name" xml:lang="EN">TestName</xs:documentation>
<xs:documentation source="Type" xml:lang="EN">TestType</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:element name="Elem2" type="Type2" minOccurs="1">
<xs:annotation>
<xs:documentation source="Name3" xml:lang="EN">TestName3</xs:documentation>
<xs:documentation source="Type3" xml:lang="EN">TestType3</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="Elem4" type="Type4" maxOccurs="99" />
</xs:sequence>
</xs:complexType>
<xs:simpleType name="Type2">
<xs:restriction base="xs:string">
<xs:pattern value="[A-Z]{9,9}"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="Type4">
<xs:annotation>
<xs:documentation source="Name5" xml:lang="EN">TestName5</xs:documentation>
<xs:documentation source="Type5" xml:lang="EN">TestType5</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:string">
<xs:pattern value="[A-Z]{7,9}"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>
我的脚本:
#!/opt/perl/bin/perl -w
use strict;
use warnings;
use XML::LibXML qw( );
use XML::LibXML::XPathContext qw( );
use File::Copy;
use File::Basename;
my $in_qfn = $ARGV[0];
my ($parser, $doc, $root, $out_qfn);
my ($name, $path, $suffix);
my ($documentroot, $complexdoc, $copyelem, $test, $fnd_type, $parent);
my @files = glob "$in_qfn/*.xsd";
foreach my $file (@files) {
print "###LI### 1 $file\n";
($name, $path, $suffix) = fileparse($file);
$out_qfn = "${name}NoRoot.${suffix}";
$parser = XML::LibXML->new();
$doc = $parser->parse_file($file);
$root = $doc->documentElement();
my $xpc = XML::LibXML::XPathContext->new($doc);
$xpc->registerNs('xsd', 'http://www.w3.org/2001/XMLSchema');
# Get the RootNode element node and delete it
foreach $test ($xpc->findnodes("//xsd:element", $root)) {
$fnd_type = $test->getAttribute('type') or next;
if ( $xpc->findnodes('./@name[.="RootNode"]', $test) ) {
foreach my $fnd_node ($xpc->findnodes('./@name[.="RootNode"]', $test)) {
$fnd_type = $fnd_node->getAttribute('type') or next;
$parent = $fnd_node->[0]->parentNode;
$parent->removeChild($fnd_node->[0]);
}
}
}
# Get the RootNode Complext Type node
foreach $test ($xpc->findnodes("//xsd:complexType", $root)) {
if ($xpc->findnodes('./@name[.="RootNode"]', $root)) {
$complexdoc = $xpc->findnodes('./@name[.="RootNode"]', $root);
$copyelem = $xpc->findnodes("//xsd:element", $complexdoc);
# Copy the element node within RootNode node to the top level
$root->appendChild($copyelem->cloneNode(1));
}
}
$doc->toFile($out_qfn);
}
但是,脚本抛出错误:
Can't locate object method "getAttribute" via package "XML::LibXML::NodeList"
感谢任何帮助。
【问题讨论】:
-
请先添加
strict和warnings。 -
你也可以发布预期的结果吗?
-
@choroba,已更新。