LibXML 查找节点($查询)
LibXML findnodes($query)
我在使用这段代码时遇到了一些问题:
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 查询应该 return 一个节点。
"funny" 的事情是,如果我使用:
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>
您输入的 XML 文档位于 默认命名空间:
<notizie xmlns="http://www.9armonie.com/news"/>
此元素及其所有后代都在该命名空间中,像 //notizie
这样的表达式永远不会成功,因为它会查找没有命名空间的元素。
另一方面,这也是 /*/*
returns 元素的原因 - 因为 *
匹配任何(或没有)命名空间中的元素。真的没什么好笑的。
要么在您的 Perl 代码中声明此名称空间(更好的选择),要么在您的 XPath 表达式中忽略名称空间。
正在用 Lib 声明命名空间XML
我相信在 LibXML 中声明名称空间是用 registerNs()
完成的,请参阅 relevant CPAN page。从输入 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"/>
我在使用这段代码时遇到了一些问题:
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 查询应该 return 一个节点。
"funny" 的事情是,如果我使用:
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>
您输入的 XML 文档位于 默认命名空间:
<notizie xmlns="http://www.9armonie.com/news"/>
此元素及其所有后代都在该命名空间中,像 //notizie
这样的表达式永远不会成功,因为它会查找没有命名空间的元素。
另一方面,这也是 /*/*
returns 元素的原因 - 因为 *
匹配任何(或没有)命名空间中的元素。真的没什么好笑的。
要么在您的 Perl 代码中声明此名称空间(更好的选择),要么在您的 XPath 表达式中忽略名称空间。
正在用 Lib 声明命名空间XML
我相信在 LibXML 中声明名称空间是用 registerNs()
完成的,请参阅 relevant CPAN page。从输入 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"/>