2017-11-02 4 views
-1

Ich versuche, den Wert des name Attributs von section Elementen in einigen XML-Daten zu erhalten.Ruft den Wert des Attributs eines Elements ab

Kann jemand bitte erklären, was mit dieser Syntax falsch ist?

Bitte beachten Sie, dass die Variable $fileLocation hier den Speicherort für das XML öffnet, mit dem ich arbeite.

+0

Verwenden Sie 'XML :: LibXML'? – Borodin

+0

'// section [/ @ name]' bedeutet "' section' Elemente im NULL-Namespace, die ein Root-Element mit einem Attribut namens 'name' im NULL-Namespace haben." Auf der anderen Seite bedeutet '// section [@name]' "section' Elemente im NULL-Namespace, die im Namespace ein Attribut namens' name' haben. " – ikegami

Antwort

2

Ich gehe davon aus, dass Sie XML::LibXML verwenden?

Es ist sehr wichtig zu erklären, welche Werkzeuge (Bibliothek, Sprache, Betriebssystem) Sie verwenden, sowie das fehlerhafte Verhalten, das Sie sehen.

Ihr "Bitte beachten Sie, dass die Variable $fileLocation hier den Speicherort für die XML, mit der ich arbeite, öffnet" ist beunruhigend. Es macht nicht viel Sinn (es ist eine Variable und kann nichts öffnen) und der von Ihnen gewählte Bezeichner bedeutet, dass es sich um einen Pfad zur XML-Datei handelt. Aber um findnodes darauf aufrufen zu können, muss es ein DOM-Objekt sein, genauer gesagt eine Instanz von XML::LibXML::Node oder eine Unterklasse.

Ihr Code sollte so aussehen

use XML::LibXML; 

my $xml_file = '/path/to/file.xml'; 

my $dom = XML::LibXML->load_xml(
    location => $xml_file 
); 

my @sections = $dom->findnodes('//section'); 

for my $section (@sections) { 
    next unless $section->hasAttribute('name'); 
    say $section->getAttribute('name'); 
} 

Das Ergebnis der findnodes Methode in Skalarkontext ist kein einziges XML::LibXML::Node Objekt, sondern ein XML::LibXML::NodeList, , die überlastet ist, so dass es bahaves Ähnlich wie eine Referenz auf ein Array

Sie sagen nicht, welche Fehler Sie bekommen, aber von Ihrem "Kann jemand bitte erklären, was mit diesem s falsch ist Yntax? " Ich stelle mir vor, dass das Modul Ihren XPath-Ausdruck ablehnt?

In dieser Erklärung

my $some_att = $fileLocation->findnodes("//section[/@name]") 

das Problem ist mit dem Prädikat [/@name] die, wenn es richtig wäre, würde filtern die section Elemente nur diejenigen enthalten, die ein name Attribut haben. Weil es ein Prädikat braucht es keine Kind Achse, und so sollte //section[@name]

geschrieben werden, aber das wird nur alle section Elemente finden, die ein name Attribut haben. So wählen Sie sich die Attribute müssen Sie //section/@name, so etwas wie dieses

my $section_names = $fileLocation->findnodes('//section/@name') 

schreiben Dann werden Sie ein XML::LibXML::NodeList von XML::LibXML::Attr Objekte haben, und Sie können die Liste ihrer Werte extrahieren etwas mit ähnlich wie

my @section_names = map { $_->value } $section_names->get_nodelist 

Sie können stattdessen lieber mit einer Liste aller section Elemente unter Verwendung des XPath-Ausdrucks //section beginnen.Das würde Ihnen eine Sammlung von XML::LibXML::Element Objekte, von dem Sie das name Element extrahieren kann mit $elem->getAttribute('name')

Denken Sie daran, dass Sie mit Arrays statt XML::LibXML::NodeList Objekten arbeiten können, wenn Sie es vorziehen, Listen-Kontext statt Skalarkontext Wahl in dem Aufruf von findnodes wie in Mob Antwort beschrieben

+0

Eigentlich ist der Ausdruck syntaktisch gültig, gibt aber immer eine leere Sequenz zurück. –

1

ich weiß Perl nicht, aber ich nehme an, dass findnodes() ausgelegt ist, einen XPath-Ausdruck auszuwerten. Ihr Ausdruck

"//section[/@name]" 

ist syntaktisch korrekt, aber semantisch, es ist Unsinn. (Abgesehen davon frage ich mich, wie die Leute auf solche Dinge kommen? Ich kann mir nur vorstellen, dass Sie aus Beispielen schneiden und einfügen, die Sie nicht verstehen, ohne jemals zur Spezifikation zurückzukehren, um zu sehen, was es eigentlich bedeutet).

Zwei Hauptfehler hier.

  • Zum einen stellen eckigen Klammern ein Prädikat oder Filter: Sie Auswahl der Abschnitte sind, die einige Bedingungen erfüllen, aber Ihre Prosa Anforderung (a) sagt, dass Sie Namen abrufen möchten (nicht Abschnitte) und (b) sagt nichts über das Filtern der Liste.
  • Zweitens ist /@name ungültig. Ein '/' am Anfang eines Ausdrucks wählt den Wurzelknoten (Dokument) aus, während @name ein Attribut auswählt. Dokumentknoten haben keine Attribute, so dass nichts ausgewählt wird.

Der gewünschte Ausdruck ist //section/@name. (Was Sie mit den Namen machen, sobald Sie sie in Perl-Raum bekommen, ist außerhalb meines Wissens.)

+0

'XML :: LibXML' ist nur ein Perl-Wrapper für' libxml2', der über [eine beliebige Anzahl von Sprachbindungen und Wrappern] verfügt (http://xmlsoft.org/python.html). Wenn Sie die Bibliothek in einer beliebigen Sprache kennen (und es ist schwer, davon abzukommen, wenn Sie mit XML-Daten arbeiten), sollten die Perl-Ideen und -Klassen das widerspiegeln, was Sie bereits gut kennen. – Borodin

+0

Danke Michael. Natürlich hast du recht. Die Entwicklung einer XSLT-Engine bewirkt Wunder für die XPath-Syntax! Der Autor * "Kann mir bitte jemand erklären, was mit dieser Syntax nicht stimmt?" * Führte mich zu der Annahme, dass ein Syntaxfehler gemeldet wurde, und ich bin nicht sicher genug mit meinen XPath-Kenntnissen, um das abzulehnen. (Übrigens, ich habe in Reading graduiert, arbeite mit Algol 68 auf Lochkarten auf einer ICL 1904S!) – Borodin

Verwandte Themen