Perl或xslt:将名为type的XML模式转换为匿名类型

时间:2017-01-17 19:29:45

标签: xml perl xslt xslt-1.0

我正在尝试使用Perl脚本或xslt将命名复杂类型转换为XML Schema中的匿名类型。

元素名称和类型可以是任何动态的。

XML架构示例:

<xsd:element name="person" type="Person"/>
<xsd:element name="person2" type="Person"/>
<xsd:complexType name="Person">
  <xsd:sequence>
    <xsd:element name="first" type="xsd:string"/>
    <xsd:element name="last" type="xsd:string"/>
  </xsd:sequence>
</xsd:complexType>

将转换为:

<xsd:element name="person">
  <xsd:complexType>
    <xsd:sequence>
      <xsd:element name="first" type="xsd:string"/>
      <xsd:element name="last" type="xsd:string"/>
    </xsd:sequence>
  </xsd:complexType>
</xsd:element>
<xsd:element name="person2">
  <xsd:complexType>
    <xsd:sequence>
      <xsd:element name="first" type="xsd:string"/>
      <xsd:element name="last" type="xsd:string"/>
    </xsd:sequence>
  </xsd:complexType>
</xsd:element>

任何帮助将不胜感激!

1 个答案:

答案 0 :(得分:1)

它只是一个XML文件,因此请使用您喜欢的XML解析器。

/path/dir/node_modules/tofjs-full

输入:

use XML::LibXML               qw( );
use XML::LibXML::XPathContext qw( );

sub resolve_qname {
   my ($context_node, $qname) = @_;
   my $local_part = $qname;
   my $namespace = $local_part =~ s/^([^:]*)://
       ? $context_node->lookupNamespaceURI($1) // $1 : '';
   return "{$namespace}$local_part";
}

my $in_qfn  = '...';
my $out_qfn = '...';

my $parser = XML::LibXML->new();
my $doc    = $parser->parse_file($in_qfn);
my $root   = $doc->documentElement();

my $xpc = XML::LibXML::XPathContext->new();
$xpc->registerNs(xs => 'http://www.w3.org/2001/XMLSchema');

my %unsupported;

my %type_nodes_by_name;
for my $type_node ($xpc->findnodes('xs:complexType', $root)) {
   my $type_name = $type_node->getAttribute('name')
      or next;

   $type_node->removeAttribute('name');
   $type_nodes_by_name{resolve_qname($type_node, $type_name)} = $type_node;
}

for my $element_node ($xpc->findnodes('//xs:element', $root)) {
   my $type_name = $element_node->getAttribute('type')
      or next;

   my $type_node = $type_nodes_by_name{resolve_qname($element_node, $type_name)}
      or next;

   $element_node->removeAttribute('type');
   $element_node->appendChild($type_node->cloneNode(1));
}

for my $type_node (values(%type_nodes_by_name)) {
   $type_node->parentNode()->removeChild($type_node);
}

$doc->toFile($out_qfn);

输出(在美化后):

<?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <xsd:element name="person" type="Person"/>
  <xsd:element name="person2" type="Person"/>
  <xsd:complexType name="Person">
    <xsd:sequence>
      <xsd:element name="first" type="xsd:string"/>
      <xsd:element name="last" type="xsd:string"/>
    </xsd:sequence>
  </xsd:complexType>
</xsd:schema>

<?xml version="1.0"?> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <xsd:element name="person"> <xsd:complexType> <xsd:sequence> <xsd:element name="first" type="xsd:string"/> <xsd:element name="last" type="xsd:string"/> </xsd:sequence> </xsd:complexType> </xsd:element> <xsd:element name="person2"> <xsd:complexType> <xsd:sequence> <xsd:element name="first" type="xsd:string"/> <xsd:element name="last" type="xsd:string"/> </xsd:sequence> </xsd:complexType> </xsd:element> </xsd:schema> 不是accurate,但可能还不错。