如何使用Perl的XML :: LibXML编写具有限定名称的XPath?

时间:2010-04-21 08:26:19

标签: xml perl xpath

我在http://www.perlmonks.org/?node_id=606909

上找到了这个
  

以合格的名字查找...
  在这种情况下,您可以在任何节点上调用findnodes方法,您不需要XML :: LibXML :: XPathContext及其前缀=>名称空间映射   $ doc-> findnodes('// / info / fooTransaction / transactionDetail / [name()=“histFile:transactionSummary”] / *');

我必须编辑我的xpath以使我的脚本在没有XPathContext的情况下工作?

#!/usr/bin/env perl
use warnings; use strict;
use 5.012;
use XML::LibXML;


my $parser = XML::LibXML->new;
$parser->recover_silently( 1 );

my $doc = $parser->parse_file( 'http://www.heise.de/' );

my $xc = XML::LibXML::XPathContext->new( $doc->getDocumentElement );
$xc->registerNs( 'xmlns', 'http://www.w3.org/1999/xhtml' );

my $nodes = $xc->findnodes( '//xmlns:h2/xmlns:a' );
for my $node ( $nodes->get_nodelist ) {
    say $_->getName, '=', $_->getValue for $node->attributes;
}

1 个答案:

答案 0 :(得分:1)

遵循文章中给出的相同模型。如果要测试节点的文本名称,而不是考虑节点的命名空间映射到的URI,请调用name并进行字符串比较。

//*[name() = "xmlns:h2"]/*[name() = "xmlns:a"]

要使该表达式匹配任何内容,文档中的节点必须名为xmlns:h2。你需要有这样的文件:

<xmlns:h2>
  <xmlns:a>header</xmlns:a>
</xmlns:h2>

但是,您链接到的页面看起来并不像那样。它使用普通的HTML节点名称,如h2a,而不是xmlns:h2。简单名称确实在xmlns命名空间中,但仅仅因为它被配置为文档的默认命名空间。由于节点未使用名称空间前缀命名,因此请勿在名称字符串中包含该前缀:

//*[name() = "h2"]/*[name() = "a"]

如果某些节点使用xmlns前缀而不是其他节点,则可以进行进一步的更改,即使用local-name代替name ;然后它将删除任何存在的名称空间前缀。

//*[local-name() = "h2"]/*[local-name() = "a"]