2009-06-08 5 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는에서 하나를 얻을해야하는 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

을로 변경 (워드 프로세서도이 언급). 컨텍스트를 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를 사용하여 더 나을 것입니다. 코드는 매우 유사합니다.

+0

감사합니다. - 이제는 잘 작동합니다. 필자가 권고 한대로 XML : LibXML을 살펴 보겠습니다. – Dror

5

undef에서 메서드를 호출 할 때 오류가 표시됩니다. undef에서 메서드를 호출하는 가장 일반적인 이유는 생성자 메서드가 성공적인지 확인하지 못하기 때문입니다. 당신이 :: 두 번째 XML을 생성 된 XPath 객체는 안 차스가 언급 한 바와 같이

$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

+2

Offhand, 당신의 문제는 당신이 $ xp에 두 번째로 할당하여 원래의 객체를 파괴하고 있다는 것입니다. –

+0

필자는 Perl을 처음 사용합니다. 현재 진행중인 작업을 처리 할 수있는 올바른 방법의 샘플을 제공 할 수 있습니까? – Dror

관련 문제