您的输入 XML 文档位于默认命名空间:
<notizie xmlns="http://www.9armonie.com/news"/>
该元素及其所有后代都在该名称空间中,并且像这样的表达式//notizie
永远不会成功,因为它寻找没有名称空间的元素。
另一方面,这也是原因/*/*
返回元素 - 因为*
匹配任何(或没有)命名空间中的元素。这确实没有什么好笑的。
要么在 Perl 代码中声明此命名空间(更好的选择),要么忽略 XPath 表达式中的命名空间。
使用 LibXML 声明命名空间
我相信在 LibXML 中声明命名空间是通过registerNs()
,参见相关 CPAN 页面 http://search.cpan.org/~shlomif/XML-LibXML-2.0117/lib/XML/LibXML/XPathContext.pod#Namespaces。从输入 XML 中声明命名空间 URI 以及prefix (news:
,在此示例中),然后您可以使用它来限定 XPath 表达式中的元素名称。
my $xpc = XML::LibXML::XPathContext->new($doc);
$xpc->registerNs('news', 'http://www.9armonie.com/news');
my $query = '/news:notizie/news:news[@id='.$newsId.']';
my $node = $xpc->findnodes($query)->get_node(1);
忽略命名空间
第二个选项意味着将 XPath 表达式修改为
"/*[local-name() = 'notizie']/*[local-name() = 'news' and @id='.$newsId.']"
上述表达式将找到notizie
以下所有文档中的元素:
<!--No namespace-->
<notizie/>
<!--Namespace with prefix-->
<news:notizie xmlns:news="http://www.9armonie.com/news"/>
<!--Default namespace-->
<notizie xmlns="http://www.9armonie.com/news"/>