2011-01-14 21 views
32

Ich versuche, das dc:title Element mit einem Xpath herausziehen. Ich kann die Metadaten mit dem folgenden Code abrufen.Nokogiri/Xpath Namespace Abfrage

doc = <<END 
<?xml version="1.0" encoding="UTF-8"?> 
<package xmlns="http://www.idpf.org/2007/opf" version="2.0"> 
    <metadata xmlns:dc="URI"> 
    <dc:title>title text</dc:title> 
    </metadata> 
</package> 
END 

doc = Nokogiri::XML(doc) 

# Awesome this works! 
puts '//xmlns:metadata' 
puts doc.xpath('//xmlns:metadata') 
# => <metadata xmlns:dc="URI"><dc:title>title text</dc:title></metadata> 

Wie Sie sehen, scheint das oben genannte korrekt zu funktionieren. Jedoch scheint ich nicht in der Lage zu sein, die Titelinformationen von diesem Knotenbaum zu erhalten, alle der folgenden scheitern.

Könnte jemand bitte erklären, wie Namespaces in einem xpath mit dem obigen xml doc verwendet werden sollten.

Antwort

60

Alle Namespaces müssen beim Parsen registriert werden. Nokogiri registriert automatisch Namespaces auf dem Root-Knoten. Alle Namespaces, die sich nicht auf dem Root-Knoten befinden, müssen Sie selbst registrieren. Das sollte funktionieren:

puts doc.xpath('//dc:title', 'dc' => "URI") 

Alternativ können Sie Namespaces insgesamt entfernen. Tun Sie dies nur, wenn Sie sicher sind, dass keine kollidierenden Knotennamen vorhanden sind.

doc.remove_namespaces! 
puts doc.xpath('//title') 
+0

Super funktioniert perfekt, danke! – Jamie

+3

+1 Ja remove_namespaces FTW! –

+1

Danke !!! Das ist Magie! – Jirapong

1

Mit richtig Präfix registriert opf für 'http://www.idpf.org/2007/opf' NamespaceURI und dc für 'URI', benötigen Sie:

/*/opf:metadata/dc:title 

Hinweis: xmlns und xml vorbehalten Präfixe, die nicht auf andere Namespace gebunden werden können URI als die eingebaute 'http://www.w3.org/2000/xmlns/' und 'http://www.w3.org/XML/1998/namespace'.

+0

Scheint nicht zu funktionieren doc.xpath ('/ */opf: metadata/dc: title') # => "'evaluate': Undefinierter Namespacepräfix" – Jamie

+0

@Jamie: Hast du die Antwort tatsächlich gelesen? Der erste Satz beginnt * "Mit richtig registrierten Präfix" * ... –

+0

@Alejandro Entschuldigungen verstehe ich nicht ganz, gibt es eine Möglichkeit, es ohne das Präfix für OPF zu tun (außer die in @ Mark-Thomas Antwort beschrieben), es wäre nett, es in einer xpath Abfrage zu tun. – Jamie

0

Als Alternative einen Hash von Namespace-URIs Konstruktion explizit, können Sie die Namespace-Definitionen aus dem XML-Elemente abrufen, wo sie definiert sind.

mit Ihrem Beispiel:

# First grab the metadata node, because that's where "dc" is defined. 
metadata = doc.at_xpath('//xmlns:metadata') 

# Pass metadata's namespaces as the resolver. 
metadata.at_xpath('dc:title', metadata.namespaces) 

Beachten Sie, dass die zweite XPath könnte auch ist:

doc.at_xpath('//dc:title', metadata.namespaces).to_s 

Aber warum sucht aus der Wurzel, wenn Sie eine näheren Vorfahr? Außerdem sollten Sie das Namespace-definierende Element und seine untergeordneten Elemente als den "Bereich" des Namespace betrachten. Die Suche nach einem begrenzten Bereich ist weniger verwirrend und vermeidet kleine Fehler.