【问题标题】:XML::LibXML, namespaces and findvalueXML::LibXML、命名空间和 findvalue
【发布时间】:2014-10-14 16:47:25
【问题描述】:

我正在使用XML::LibXML 来解析带有命名空间的 XML 文档。因此,我使用 XPath //u:model 使用 XML::LibXML::XPathContextfindnodes。这会正确返回 3 个节点。

我现在想在 3 个返回的 XML::LibXML::Element 对象上使用 findvalue,但无法确定工作方法/xpath。作为替代方案,我对子节点进行迭代并直接与 nodeName 匹配,但这并不理想:

use strict;
use warnings;

use XML::LibXML;
use XML::LibXML::XPathContext;

my $dom = XML::LibXML->load_xml( IO => \*DATA );
my $context = XML::LibXML::XPathContext->new( $dom->documentElement() );
$context->registerNs( 'u' => 'http://www.ca.com/spectrum/restful/schema/response' );

for my $node ( $context->findnodes('//u:model') ) {
    #my $mh = $node->findvalue('mh');
    my ($mh)
        = map { $_->textContent() }
        grep  { $_->nodeName() eq 'mh' } $node->childNodes();

    #my $attr = $node->findvalue('attribute');
    my ($attr)
        = map { $_->textContent() }
        grep  { $_->nodeName() eq 'attribute' } $node->childNodes();

    print "mh = $mh, attr = $attr\n";
}

__DATA__
<root xmlns="http://www.ca.com/spectrum/restful/schema/response">
  <error>EndOfResults</error>
  <throttle>86</throttle>
  <total-models>86</total-models>
  <model-responses>
    <model>
      <mh>0x100540</mh>
      <attribute id="0x1006e">wltvbswfc02</attribute>
    </model>
    <model>
      <mh>0x100c80</mh>
      <attribute id="0x1006e">wltvsutm1ds02</attribute>
    </model>
    <model>
      <mh>0x100c49</mh>
      <attribute id="0x1006e">wltvsdora03</attribute>
    </model>
  </model-responses>
</root>

输出:

mh = 0x100540, attr = wltvbswfc02
mh = 0x100c80, attr = wltvsutm1ds02
mh = 0x100c49, attr = wltvsdora03

有没有办法使用注释掉的行来查找节点,而不是间接迭代子节点的方法?还是有另一种方法来解决这个问题以获得配对值?

【问题讨论】:

    标签: xml perl xml-libxml


    【解决方案1】:

    你不能使用$node-&gt;findvalue(),因为整个默认命名空间的东西。但是,您可以重用您的 XML::LibXML::XPathContext 对象来查找所需的值:

    for my $node ( $context->findnodes('//u:model') ) {
       my $mh   = $context->findvalue('u:mh', $node);
       my $attr = $context->findvalue('u:attribute', $node);
       print "mh = $mh, attr = $attr\n";
    }
    

    【讨论】:

    • 谢谢,这正是我想要的。顺便说一句,我发现了一个可以完全忽略命名空间的替代解决方案。
    【解决方案2】:

    XPath 允许使用函数local-name 忽略命名空间:

    use XML::LibXML;
    
    my $dom = XML::LibXML->load_xml( IO => \*DATA );
    
    for my $node ( $dom->findnodes('//*[local-name()="model"]') ) {
        my $mh   = $node->findvalue('*[local-name()="mh"]');
        my $attr = $node->findvalue('*[local-name()="attribute"]');
    
        print "mh = $mh, attr = $attr\n";
    }
    

    这消除了像问题中那样为单个命名空间文档指定上下文的需要。

    参考:Re^2: XML::LibXML and namespaces

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-25
      • 2015-10-25
      • 1970-01-01
      相关资源
      最近更新 更多