2014-09-02 61 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