5 Stimmen

Wie verwende ich XPath auf Knoten mit einem Präfix, aber ohne Namensraum?

Ich habe eine XML-Datei, die ich parsen muss. Ich habe keine Kontrolle über das Format der Datei und kann es nicht ändern.

Die Datei verwendet ein Präfix (nennen wir es a), definiert jedoch keinen Namespace für dieses Präfix irgendwo. Es scheint, dass ich xpath nicht verwenden kann, um Knoten mit dem a Namespace abzufragen.

Hier ist der Inhalt des XML-Dokuments

  stuff0
  stuff1
  stuff2
  stuff3
  stuff4
  stuff5
  stuff6
  stuff7
  stuff8
  stuff9

Ich verwende Nokogiri, um das Dokument abzufragen:

doc = Nokogiri::XML(open('text.xml'))
things = doc.xpath('//a:thing')

Die Abfrage schlägt fehl und gibt den folgenden Fehler zurück:

Nokogiri::XML::XPath::SyntaxError: Undefinierter Namensraum-Präfix: //a:thing

Aus meiner Recherche habe ich herausgefunden, dass ich den Namespace für das Präfix in der xpath-Methode angeben könnte:

things = doc.xpath('//a:thing', a: 'niemand weiß')

Dies liefert ein leeres Array zurück.

Was wäre der beste Weg für mich, die benötigten Knoten zu erhalten?

5voto

Justin Ko Punkte 46101

Das Problem ist, dass der Namespace im XML-Dokument nicht richtig definiert ist. Nokogiri sieht deshalb die Knotennamen als "a:root" anstatt "a" als Namespace und "root" als Knotennamen:

xml = %Q{

      stuff0
      stuff1

}
doc = Nokogiri::XML(xml)
puts doc.at_xpath('*').node_name
#=> "a:root"
puts doc.at_xpath('*').namespace
#=> ""

Lösung 1 - Knotennamen mit Doppelpunkt angeben

Eine Lösung besteht darin, nach Knoten mit dem Namen "a:thing" zu suchen. Sie können nicht //a:thing machen, da XPath das "a" als Namespace behandeln wird. Sie können dies umgehen, indem Sie //*[name()="a:thing"] machen:

xml = %Q{

      stuff0
      stuff1

}
doc = Nokogiri::XML(xml)
things = doc.xpath('//*[name()="a:thing"]')
puts things
#=> stuff0
#=> stuff1

Lösung 2 - Ändern Sie das XML-Dokument, um den Namespace zu definieren

Eine alternative Lösung besteht darin, die XML-Datei zu ändern, um den Namespace ordnungsgemäß zu definieren. Das Dokument wird dann wie erwartet mit Namespaces funktionieren:

xml = %Q{

      stuff0
      stuff1

}
xml.gsub!('', '')
doc = Nokogiri::XML(xml)
things = doc.xpath('//a:thing')
puts things
#=> stuff0
#=> stuff1

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X