LibXML findnodes($ query) [英] LibXML findnodes($query)

查看:64
本文介绍了LibXML findnodes($ query)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在使用此代码时遇到了一些麻烦:

I'm having some trouble with this code:

my $file= '../xml/news.xml';
my $parser= XML::LibXML->new();
my $doc = $parser->parse_file($file);
my $xpc = XML::LibXML::XPathContext->new($doc);
my $query = '/notizie/news[@id='.$newsId.']';
print $query;
my $node = $xpc->findnodes($query)->get_node(1);

print $node;

特别是"print $ node"打印一个空字符串,即使XML文件路径正确并且XPath查询应该返回一个节点.

In particular "print $node" prints an empty string, even if the XML file path is correct and the XPath query should return a node.

有趣"的事情是,如果我使用:

The "funny" thing is that if i use:

my $query = '/*/*[@id='.$newsId.']'; 

我得到了正确的结果.

这是news.xml文件:

This is the news.xml file:

<?xml version="1.0"?>
<notizie xmlns="http://www.9armonie.com/news"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://www.9armonie.com/news news.xsd">
    <news id="3">
        <data>2015-01-01</data>
        <ora>12:00:00</ora>
        <titolo>Title 3</titolo>
        <descrizione> Description 3</descrizione>
    </news>     
    <news id="2">
        <data>2014-12-19</data>
        <ora>12:00:00</ora>
        <titolo>Title 2</titolo>
        <descrizione> Description 2</descrizione>
    </news>
    <news id="1">
        <data>2014-12-18</data>
        <ora>12:00:00</ora>
        <titolo>News 1</titolo>
        <descrizione> Desc 1</descrizione>
    </news>
    <news id="0">
        <data>2014-12-18</data>
        <ora>12:00:00</ora>
        <titolo> asdasd</titolo>
        <descrizione> First! </descrizione>
    </news>
</notizie>

推荐答案

您输入的XML文档位于默认名称空间中:

Your input XML document is in a default namespace:

<notizie xmlns="http://www.9armonie.com/news"/>

该元素及其所有后代均位于该命名空间中,而//notizie 之类的表达式将永远不会成功,因为它查找的是没有命名空间的元素.

This element and all its descendants are in that namespace, and an expression like //notizie will never be successful because it looks for an element without a namespace.

另一方面,这也是/*/* 返回元素的原因-因为 * 匹配任何(或没有)命名空间中的元素.真的没有什么可笑的.

On the other hand, that's also why /*/* returns the elements - because * matches elements in any (or no) namespace. There is nothing funny about it really.

要么在Perl代码中声明此名称空间(更好的选择),要么在XPath表达式中忽略名称空间.

Either declare this namespace in your Perl code (the better option), or ignore namespaces in your XPath expression.

使用LibXML声明名称空间

我相信LibXML中的名称空间声明是通过 registerNs()完成的,请参见

I believe declaring namespaces in LibXML is done with registerNs(), see the relevant CPAN page. Declare the namespace URI from the input XML together with a prefix (news:, in this example) that you can then use to qualify the element names in the XPath expression.

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表达式修改为

The second option means modifying your XPath expression to

"/*[local-name() = 'notizie']/*[local-name() = 'news' and @id='.$newsId.']"

以上表达式将在以下所有文档中找到 notizie 元素:

The above expression will find the notizie element in all of the following documents:

<!--No namespace-->
<notizie/>

<!--Namespace with prefix-->
<news:notizie xmlns:news="http://www.9armonie.com/news"/>


<!--Default namespace-->
<notizie xmlns="http://www.9armonie.com/news"/>

这篇关于LibXML findnodes($ query)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆