XML :: LibXML - 查找(和注册)文档中使用的命名空间

时间:2011-09-12 13:21:47

标签: xml perl namespaces

我从第三方解析Xml时遇到问题;他们发送了几个不同版本的xml,具有重叠的命名空间;


版本1

富= “瓮:bar.org/version-1”

远= “瓮:gle.org/version-1”


第2版

富= “栏:a.org/version-2”

远= “GLE:a.org/version-2”


以前(当我只需要处理一个版本时)我会从硬编码的哈希中注册名称空间,如下所示:

#!/usr/bin/perl

use strict;
use XML::LibXML ;

my $cfg->{namespace} = {
    foo=>"urn:bar.org/version-1",
    far=>"urn:gle.org/version-1",
};

my $parser = XML::LibXML->new({recover => '1'});

my $doc = $parser->parse_string($inputHash->{$key}->{xml});

my $xc = XML::LibXML::XPathContext->new( $doc->documentElement() );

for my $ns (keys %{$cfg->{namespace}})
{
    $xc->registerNs($ns => $cfg->{namespace}->{$ns});
}

显然这只适用于版本1 ..

已经扫描了LibXML文档,但看不到提取文档中使用的命名空间并注册它们的方法;请问有人给我一个指针吗?

Pseudo doc:

<?xml version="1.0"?>
<foo:Parent xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:foo="bar:a.org/version-2">
    <far:Child xmlns:gle="gle:a.org/version-2">
    {horrific structure with more ns declarations all of which need registering}
    </far:Child>
</foo:Parent>

3 个答案:

答案 0 :(得分:7)

离开this answer,我会使用//namespace::* XPath表达式来查找命名空间。试试这个代码示例,看看它是否有帮助:

use strict;
use warnings;
use XML::LibXML;

my $cfg;
my $xml = XML::LibXML->load_xml( location => <your xml>);
foreach my $node ($xml->findnodes('//namespace::*')) {

    $cfg->{namespace}{$node->getLocalName()} = $node->getValue();
}

这应该用您需要的东西填充哈希值。此外,并不总是支持此XPath表达式。我使用LibXML 1.70和dll版本20703进行了测试,它对我有用。

答案 1 :(得分:0)

我会尝试XML :: LibXML :: Node :: lookupNamespaceURI,即

$cfg->{namespace}->{foo} = $node->lookupNamespaceURI("foo");

对于某个节点足够深,以便它具有声明。要使用的最简单的节点是文档,但除非在顶部声明名称空间,否则这将无效;最通用的方法是遍历所有节点,并根据您的应用程序逻辑处理相同前缀的情况被重用于不同的命名空间......

答案 2 :(得分:0)

迭代树寻找命名空间,直到找到一个,比如使用getElementsByTagName或其他一些

#!/usr/bin/perl --

use strict;
use warnings;

use XML::Twig;

my $xml = <<'__XML__';
<?xml version="1.0"?>
<!-- initially, the default namespace is "books" -->
<book xmlns='urn:loc.gov:books'
      xmlns:isbn='urn:ISBN:0-395-36341-6'>
    <title>Cheaper by the Dozen</title>
    <isbn:number>1568491379</isbn:number>
    <notes>
      <!-- make HTML the default namespace for some commentary -->
      <p xmlns='urn:w3-org-ns:HTML'>
          This is a <i>funny</i> book!
      </p>
    </notes>
</book>
__XML__

{
    my $t = XML::Twig->new(
        start_tag_handlers => {
            _all_ => sub {
                my $tag = $_[1]->tag;
                my $nsp = $_[1]->ns_prefix||'';
                print "$tag => $nsp\n";
                print map {
                    join ' ',
                        "\t", $_,' => ', $_[1]->att($_), "\n"
                    } grep /xmlns/ , $_[1]->att_names ;
            },
        },
    );
    $t->parse($xml);
}
__END__
book =>
         xmlns  =>  urn:loc.gov:books
         xmlns:isbn  =>  urn:ISBN:0-395-36341-6
title =>
isbn:number => isbn
notes =>
p =>
         xmlns  =>  urn:w3-org-ns:HTML
i =>