2009-06-08 10 views
3

Ich möchte XML-Dateien mit xPaths analysieren. Nach dem Abrufen eines Knotens muss ich möglicherweise xPath-Suchen an den übergeordneten Knoten durchführen. Meine aktuellen Code XML::XPath Verwendung ist:Wie verwende ich XML :: XPath, um einen Elternknoten zu erhalten?

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"; 
     } 
    } 
} 

Mein Ziel ist es, einen Hash-Wert von foo Elemente Namen und ihre Bar untergeordneten Knoten Werte zu erhalten, wenn ein foo es keinen Strich Knoten haben sollte man von der übergeordneten foo erhalten oder foos Knoten.

Für diese XML:

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

Ich würde erwarten:

number1->bar1 
number2->GlobalBar 

Wenn Sie den obigen Code verwenden ich eine Fehlermeldung erhalten, wenn sie versuchen übergeordneten Knoten zu erhalten:

Can‘ t Aufrufmethode "getNodeType" auf einem undefinierten Wert

Jede Hilfe wird sehr geschätzt!

Antwort

4

zu sein, wie Chas erwähnt, sollten Sie nicht ein zweites XML :: XPath-Objekt erstellen (die docs erwähnen dies auch). Sie können entweder den Kontext als zweiten Parameter der Methode find * übergeben oder einfach die Methoden auf dem Context-Knoten aufrufen, wie Sie es tatsächlich getan haben, um $ FooName zu erhalten.

Sie haben auch einige Methodenaufrufe, die nicht das tun, was Sie denken (getNodeType gibt nicht den Elementnamen, sondern eine Zahl zurück, die den Knotentyp darstellt).

Insgesamt ist die aktualisierte Code unten scheint, Sie zu geben, was Sie wollen:

#!/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"; 
     } 
    } 
} 

Schließlich ein Wort der Warnung: XML::XPath nicht gut gepflegt wird, und Sie würden wahrscheinlich besser dran mit XML::LibXML statt. Der Code wäre sehr ähnlich.

+0

Danke - es funktioniert jetzt gut. Ich werde in XML schauen: LibXML wie Sie es empfohlen haben. – Dror

5

Dieser Fehler wird angezeigt, wenn Sie versuchen, eine Methode unter undef aufzurufen. Der häufigste Grund für das Aufrufen einer Methode unter undef ist die fehlende Überprüfung, ob die Konstruktormethode erfolgreich war. Ändern

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

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

Danke für diese Antwort, aber das ist nicht das Problem. Ich weiß, dass ich die Fehlermeldung für den Versuch bekomme, eine Methode von undef aufzurufen, die Frage ist, was mache ich falsch - warum kann ich nicht den Elternknoten bekommen? Übrigens, der Konstruktor ist in Ordnung, ich habe Ihren Code benutzt und keine Nachricht erhalten. – Dror

+2

Offhand würde ich sagen, Ihr Problem ist, dass Sie das ursprüngliche Objekt zerstören, indem Sie $ xp ein zweites Mal zuweisen. –

+0

Ich bin neu in Perl, Können Sie eine Probe des richtigen Weges zur Bewältigung der Aufgabe zur Verfügung stellen? – Dror

Verwandte Themen