2014-09-02 62 views
0

我想提取XML的属性值考虑层级:的Perl和XPath:考虑层次

<?xml version="1.0" encoding="UTF-8"?> 
<database> 
    <row1s> 
    <row1 name="fox" category="mammal"> 
     <row2s> 
     <row2 type="1"/> 
     <row2 type="2"/> 
     </row2s> 
    </row1> 
    <row1 name="horse" category="mammal"> 
     <row2s> 
     <row2 type="3"/> 
     </row2s> 
    </row1> 
    <row1 name="bee" category="insect"> 
     <row2s/> 
    </row1> 
    <row1 name="wasp" category="insect"> 
     <row2s/> 
    </row1> 
    </row1s> 
</database> 

这是Perl代码我提取值:

use strict; 
use DBI; 
use XML::XPath; 
use XML::XPath::XMLParser; 

my $xrow1; 
my $xrow2; 

my $xp = XML::XPath->new (filename => "animals3.xml"); 

my $node_list1 = $xp->find ("//row1s/row1"); 

foreach my $row1 ($node_list1->get_nodelist()) { 
    $xrow1 = $row1->getAttribute("name"); 
    print "Level row1 gives: $xrow1\n"; 

    my $node_list2 = $xp->find ("//row2s/row2"); 

    foreach my $row2 ($node_list2->get_nodelist()) { 
    $xrow2 = $row2->getAttribute("type");  
    print "Level row2 gives: $xrow2\n"; 
    } 
} 

我得到的是:

Level row1 gives: fox 
Level row2 gives: 1 
Level row2 gives: 2 
Level row2 gives: 3 
Level row1 gives: horse 
Level row2 gives: 1 
Level row2 gives: 2 
Level row2 gives: 3 
Level row1 gives: bee 
Level row2 gives: 1 
Level row2 gives: 2 
Level row2 gives: 3 
Level row1 gives: wasp 
Level row2 gives: 1 
Level row2 gives: 2 
Level row2 gives: 3 

对于每个级别1,我从级别2获得所有属性值。这不是什么iw蚂蚁。我想只输出correpondent级别1的水平2项,但我要的是:

Level row1 gives: fox 
Level row2 gives: 1 
Level row2 gives: 2 
Level row1 gives: horse 
Level row2 gives: 3 
Level row1 gives: bee 
Level row1 gives: wasp 

我将不胜感激任何提示如何解决这个问题。

谢谢。

回答

3

领先/表示绝对路径。

my $node2 = $xp->find("//row2s/row2"); 

应该

my $node2 = $xp->find("row2s/row2", $row1); 

评论:

  • 无论$node1也不$node2是节点。选择更好的名字。

  • 声明你所做的变量部分无视声明它们的目的。他们应该在适当的循环中声明。

+0

非常感谢您的回答。我改变了你的建议。输出现在只给出来自1级(狐狸,马,蜜蜂,黄蜂)没有对应的2级值的属性值。如果$ node1不是节点,它是什么? $ element1会更好吗?或$ level1? – giordano 2014-09-02 15:54:05

+0

'$ node1_list'或'$ animals'是两种可能性。测试 – ikegami 2014-09-02 15:58:57

+0

哦,这是因为你的XML没有意义。尽管您的缩进意味着否则,所有'row1'元素都没有'row2s'子元素。我想你的意思是使用''你确定修正XML ,还是你需要与你拥有的代码一致的代码? – ikegami 2014-09-02 16:06:00

1

下修复和简化你的脚本:

use strict; 
use warnings; 

use XML::XPath; 
use XML::XPath::XMLParser; 

#my $xp = XML::XPath->new(filename => "animals3.xml"); 
my $xp = XML::XPath->new(ioref => \*DATA); 

for my $row1 ($xp->findnodes('//row1s/row1')){ 
    printf "Level row1 gives: %s\n", $row1->getAttribute("name"); 

    for my $row2 ($row1->findnodes('.//row2s/row2')) { 
     printf "Level row2 gives: %s\n", $row2->getAttribute("type"); 
    } 
} 

__DATA__ 
<?xml version="1.0" encoding="UTF-8"?> 
<database> 
    <row1s> 
    <row1 name="fox" category="mammal"> 
     <row2s> 
     <row2 type="1"/> 
     <row2 type="2"/> 
     </row2s> 
    </row1> 
    <row1 name="horse" category="mammal"> 
     <row2s> 
     <row2 type="3"/> 
     </row2s> 
    </row1> 
    <row1 name="bee" category="insect"> 
     <row2s/> 
    </row1> 
    <row1 name="wasp" category="insect"> 
     <row2s/> 
    </row1> 
    </row1s> 
</database> 

输出:

Level row1 gives: fox 
Level row2 gives: 1 
Level row2 gives: 2 
Level row1 gives: horse 
Level row2 gives: 3 
Level row1 gives: bee 
Level row1 gives: wasp 
+0

非常感谢。我学到了一些新的技巧。我非常感谢,如果你看看我的后续问题:[链接](http://stackoverflow.com/questions/25702607/perl-and-xpath-missing-entries-in-database-table)。 – giordano 2014-09-06 17:01:52

+0

很高兴我能帮到你。我看了一下你的新问题,但我看到鲍罗丁已经在帮助方面做了足够的工作。 – Miller 2014-09-10 23:38:59