【问题标题】:LibXML findnodes($query)LibXML findnodes($query)
【发布时间】:2015-01-28 21:54:39
【问题描述】:

我在处理这段代码时遇到了一些问题:

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 查询应该返回一个节点。

“有趣”的是,如果我使用:

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

我得到了正确的结果。

这是 news.xml 文件:

<?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>

【问题讨论】:

  • $newId 是如何填充的?还有——你在用strictwarnings吗?

标签: perl xpath libxml2


【解决方案1】:

您的输入 XML 文档位于 默认命名空间

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

此元素及其所有后代都在该命名空间中,而像 //notizie 这样的表达式将永远不会成功,因为它会查找没有命名空间的元素。

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

要么在你的 Perl 代码中声明这个命名空间(更好的选择),要么在你的 XPath 表达式中忽略命名空间。

使用 LibXML 声明命名空间

我相信在 LibXML 中声明命名空间是使用 registerNs() 完成的,请参阅 relevant CPAN page。从输入 XML 声明命名空间 URI 以及 前缀(在此示例中为 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"/>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-10
    • 2015-10-25
    • 1970-01-01
    • 2021-11-05
    • 1970-01-01
    • 2012-07-24
    相关资源
    最近更新 更多