2009-06-08 98 views
3

我想用xPath解析XML文件。獲得節點後,我可能需要在其父節點上執行xPath搜索。我使用XML::XPath當前的代碼是:如何使用XML :: XPath獲取父節點?

my $xp = XML::XPath->new(filename => $XMLPath); 
# get all foo or foos node with a name 
my $Foo = $xp->find('//foo[name] | //foos[name]'); 
if (!$Foo->isa('XML::XPath::NodeSet') || $Foo->size() == 0) { 
    # no foo found 
    return undef; 
} else { 
    # go over each and get its bar node 
    foreach my $context ($Foo->get_nodelist) { 
     my $FooName = $context->find('name')->string_value; 
     $xp = XML::XPath->new(context => $context); 
     my $Bar = $xp->getNodeText('bar'); 
     if ($Bar) { 
      print "Got $FooName with $Bar\n"; 
     } else { 
      # move up the tree to get data from parent 
      my $parent = $context->getParentNode; 
      print $parent->getNodeType,"\n\n"; 
     } 
    } 
} 

我的目標是獲得FOO元素名稱的哈希和他們的欄子節點的值,如果FOO沒有一個杆節點就應該從其父FOO中的一個或foos節點。

對於這個XML:

<root> 
    <foos> 
     <bar>GlobalBar</bar> 
     <foo> 
      <name>number1</name> 
      <bar>bar1</bar> 
     </foo> 
     <foo> 
      <name>number2</name> 
     </foo> 
    </foos> 
</root> 

我希望:

number1->bar1 
number2->GlobalBar 

當試圖獲得父節點在使用上面的代碼我得到一個錯誤:

燦」 t調用方法「getNodeType」在 未定義值

任何幫助將不勝感激!

回答

4

正如查斯所提到的,你不應該創建第二個XML :: XPath對象(該文檔提到這太)。您可以傳遞上下文作爲find *方法的第二個參數,或者只需調用上下文節點上的方法,就像事實上獲得$ FooName一樣。

您還有幾個方法調用不會做您認爲的操作(getNodeType不返回元素名稱,而是表示節點類型的數字)。

總體低於更新的代碼似乎給你想要的東西:

#!/usr/bin/perl 

use strict; 
use warnings; 

use XML::XPath; 

my $xp = XML::XPath->new(filename => "$0.xml"); 
# get all foo or foos node with a name 
my $Foo = $xp->find('//foo[name] | //foos[name]'); 
if (!$Foo->isa('XML::XPath::NodeSet') || $Foo->size() == 0) { 
    # no foo found 
    return undef; 
} else { 
    # go over each and get its bar node 
    foreach my $context ($Foo->get_nodelist) { 
     my $FooName = $context->find('name')->string_value; 
     my $Bar = $xp->findvalue('bar', $context); # or $context->findvalue('bar'); 
     if ($Bar) { 
       print "Got $FooName with $Bar\n"; 
     } else { 
       # move up the tree to get data from parent 
       my $parent = $context->getParentNode; 
       print $parent->getName,"\n\n"; 
     } 
    } 
} 

最後,提醒一句:XML::XPath沒有得到很好的維護,你會使用XML::LibXML反而可能會更好。代碼將非常相似。

5

當您嘗試調用undef上的方法時,您會看到該錯誤。在undef上調用方法的最常見原因是無法檢查構造函數方法是否成功。更改

$xp = XML::XPath->new(context => $context); 

$xp = XML::XPath->new(context => $context) 
    or die "could not create object with args (context => '$context')"; 
+0

感謝您的回答,但這不是問題。我知道我得到錯誤消息試圖調用一個undef的方法,問題是我在做什麼錯了 - 爲什麼我不能得到父節點?順便說一句,構造函數是好的,我用你的代碼,並沒有消息。 – Dror 2009-06-08 13:59:45

+2

Offhand,我會說你的問題是,你正在通過分配$ xp第二次銷燬原始對象。 – 2009-06-08 14:47:23