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



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

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

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>

任何帮助将不胜感激!

它只是一个XML文件,所以使用你最喜欢的XML解析器。

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>

resolve_qname并不准确,但可能足够好。

相关内容

  • 没有找到相关文章

最新更新