2009-05-08 7 views
5

Ich habe die folgende XML-Dokument:Wie bekomme ich Nokogiri meine Namespaces zu verstehen?

<samlp:LogoutRequest ID="123456789" Version="2.0" IssueInstant="200904051217"> 
    <saml:NameID>@[email protected]</saml:NameID> 
    <samlp:SessionIndex>abcdefg</samlp:SessionIndex> 
</samlp:LogoutRequest> 

Ich mag würde den Inhalt des SessionIndex erhalten (das heißt, ‚abcdefg‘) aus ihm heraus. Ich habe dies versucht:

XPATH_QUERY = "LogoutRequest[@ID][@Version='2.0'][IssueInstant]/SessionIndex" 
SAML_XMLNS = 'urn:oasis:names:tc:SAML:2.0:assertion' 
SAMLP_XMLNS = 'urn:oasis:names:tc:SAML:2.0:protocol' 

require 'nokogiri' 
doc = Nokogiri::XML(xml) 
doc.xpath(XPATH_QUERY, 'saml' => SAML_XMLNS, 'samlp' => SAMLP_XMLNS) 

aber ich erhalte die folgenden Fehler:

Nokogiri::XML::SyntaxError: Namespace prefix samlp on LogoutRequest is not defined 
Nokogiri::XML::SyntaxError: Namespace prefix saml on NameID is not defined 
Nokogiri::XML::SyntaxError: Namespace prefix samlp on SessionIndex is not defined 

Ich habe versucht, die Namensräume auf die XPath-Abfrage hinzufügen, aber das ändert nichts.

Warum kann ich Nokogiri nicht überzeugen, dass die Namespaces gültig sind?

Antwort

6

Es sieht nicht so aus, als wären die Namespaces in diesem Dokument korrekt deklariert - auf dem Root-Knoten sollten die Attribute xmlns:samlp und xmlns:saml stehen. In Fällen wie diesen, ignoriert Nokogiri im Wesentlichen der Namensräume (wie es sie nicht zu URIs oder URNs abbilden kann), so dass Ihre XPath funktionieren sie, wenn Sie entfernen, dh

doc.xpath(XPATH_QUERY) 
+0

liefern, scheint mir die gleichen Fehler zu geben ... in manchen Situationen. Es funktioniert buchstäblich in irb funktioniert gut, aber meine Spezifikationen laufen noch in die Luft. Garr. –

+0

Verstanden! Nokogiri gibt einen "Fehler" -Knoten zurück, der den gefundenen Knoten umschließt, aber _really_did_find_the_node_! –

9

ich eine zwei verschiedene Möglichkeiten für Sie zu sehen:

  1. alle Namespaces entfernen

    http://www.rubydoc.info/github/sparklemotion/nokogiri/Nokogiri/XML/Document#remove_namespaces%21-instance_method

    Brute-Force-Weg, es zu tun. Könnte zu Problemen bei Namespace-Kollisionen führen.

  2. Verwenden collect_namespaces

    http://www.rubydoc.info/github/sparklemotion/nokogiri/Nokogiri/XML/Document#collect_namespaces-instance_method

    Eine viel bessere Lösung. Sie könnten dies einmal verwenden, um die Namespaces (etwa in irb) zu identifizieren und sie hart zu codieren.

    OR

    es zur Laufzeit verwenden und es als das zweite Argument zu http://www.rubydoc.info/github/sparklemotion/nokogiri/Nokogiri/XML/Node#xpath-instance_method

+0

'collect_namespaces' ist eine gute Sache zu wissen – mikezter