2010-04-20 34 views
1

该脚本适用于和不适用XPathContext。我为什么要用XPathContext为什么我应该在Perl的XML :: LibXML中使用XPathContext?

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

my $parser = XML::LibXML->new; 

my $doc = $parser->parse_string(<<EOT); 
<?xml version="1.0"?> 
<xml> 
    Text im Dokument 
    <element id="myID" name="myname" style="old" /> 
    <object objid="001" objname="Object1" /> 
    <element id="002" name="myname" /> 
</xml> 
EOT 
#/ 

# without XPathContext 
my $nodes = $doc->findnodes('/xml/element[@id=002]'); 

# with XPathContext 
#my $root = $doc->documentElement; 
#my $xc = XML::LibXML::XPathContext->new($root); 
#my $nodes = $xc->findnodes('/xml/element[@id=002]'); 


for my $node ($nodes->get_nodelist) { 
    say "Node: ", $node->nodeName; 
    print "Attribute: "; 
    print $_->getName, '=', $_->getValue, ' ' for $node->attributes; 
    say ""; 
} 

回答

9

使用XPathContext元素的主要原因是名称空间。您的文档没有名称空间,因此XPathContexts不会向您的查询添加任何内容。现在,假设你实际上有以下XML

my $doc = $parser->parse_string(<<EOT); 
<?xml version="1.0"?> 
<xml xmlns="http://my.company.com/ns/nsone" 
    xmlns:ns2="http://your.company.com/nstwo"> 
    Text im Dokument 
    <ns2:element id="myID" name="myname" style="old" /> 
    <object objid="001" objname="Object1" /> 
    <element id="002" name="myname" /> 
</xml> 
EOT 

您需要以具有定义的命名空间,让你可以做名称空间感知的XPath查询定义一个XPathContext:

my $root = $doc->documentElement; 
my $xc = XML::LibXML::XPathContext->new($root); 
$xc->registerNs("ns2", "http://your.company.com/nstwo"); 
$xc->registerNs("ns1", "http://my.company.com/nsone"); 
my $nodes = $xc->findnodes('/ns1:xml/ns2:element[@id="myID"]'); 

否则,没有简单的方法来使用名称空间感知XPath语句。

+0

'/ ns1:xml/ns2:element [@ id = 002]':是ns2是ns1的子集吗? – 2010-04-20 09:40:58

+3

名称空间没有父子关系。他们彼此独立。我想证明你可以有多个命名空间。在XPath中,如果你创建了一个没有命名空间的语句,你断言你想要的是没有命名空间的元素。在我使用的示例文档中,所有元素都位于名称空间中,前缀不固定的元素位于默认名称空间中。但是,您需要在XPath语句中使用前缀。 – 2010-04-20 10:51:23

+0

Nic,你上面的例子不会找到任何节点。没有任何具有“002”标识属性值的ns2:元素标签。 xpath表达式“/ ns1:xml/ns2:element [@ id ='myID']”将返回“ns2:element”节点。 xpath表达式“/ ns1:xml/element [@ id = 002]”将返回sid_com原始示例中返回的“element”节点。 – benrifkah 2010-11-03 21:12:13

相关问题