2009-06-08 19 views
3

xPathsを使用して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から1を取得する必要があり、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

する

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

を変更します。実際に$ FooNameを取得したのと同様に、コンテキストをfind *メソッドの2番目のパラメータとして渡すか、単にコンテキストノードのメソッドを呼び出すこともできます。

あなたは思ったことをしないメソッド呼び出しもいくつかあります(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を使用したほうが良いでしょう。コードは非常に似ています。

+0

ありがとうございます - 今はうまくいきます。あなたがアドバイスしたようにXML:LibXMLを調べます。 – Dror

5

undefでメソッドを呼び出そうとすると、エラーが表示されます。 undefでメソッドを呼び出す最も一般的な理由は、コンストラクターメソッドが正常に実行されたかどうかを確認できないことです。チャスが述べたように、2番目のXML :: XPathのオブジェクトを(ドキュメントはこれも言及)を作成するべきではありません

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

この回答に感謝しますが、これは問題ではありません。私はundefのメソッドを呼び出そうとしたときにエラーメッセージが出ることを知っています。質問は私が間違っていることです - どうして私は親ノードを取得できませんか?ちなみに、コンストラクタはOKです、私はあなたのコードを使用し、メッセージを持っていません。 – Dror

+2

私はあなたの問題は、元のオブジェクトを$ xpにもう一度割り当てて破棄しているということです。 –

+0

私はPerlを使い慣れていません。手元にあるタスクを正しく処理するためのサンプルを提供できますか? – Dror

関連する問題