2009-05-08 7 views
5

je le document XML suivant:Comment obtenir que Nokogiri comprenne mes espaces de noms?

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

Je voudrais obtenir le contenu du SessionIndex (qui est « abcdefg ») hors de lui. Je l'ai essayé ceci:

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) 

mais je reçois les erreurs suivantes:

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 

J'ai essayé d'ajouter les espaces de noms pour la requête XPath, mais cela ne change rien. Pourquoi ne puis-je convaincre Nokogiri que les espaces de noms sont valides?

Répondre

6

Il ne semble pas que les espaces de noms dans ce document soient correctement déclarés - il devrait y avoir des attributs xmlns:samlp et xmlns:saml sur le nœud racine. Dans les cas comme celui-ci, Nokogiri ignore essentiellement les espaces de noms (comme il ne peut pas les associer à URIs ou URN), de sorte que votre XPath fonctionne si vous les supprimez, à savoir

doc.xpath(XPATH_QUERY) 
+0

Cela me semble donner les mêmes erreurs ... dans certaines situations. Le faire littéralement en irb fonctionne bien, mais courir mes spécifications explosent toujours. Garr. –

+0

J'ai compris! Nokogiri retourne un noeud "error" qui enveloppe le noeud qu'il a trouvé, mais il _really_did_find_the_node_! –

9

Je vois deux options différentes pour vous:

  1. Retirez tous les espaces de noms

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

    manière Brute force de le faire. Pourrait conduire à des problèmes où il y a des collisions d'espace de noms.

  2. Utilisez collect_namespaces

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

    Une bien meilleure solution. Vous pouvez l'utiliser une fois pour identifier les espaces de noms (disons dans irb) et les coder en dur.

    OU

    Utilisez lors de l'exécution et de l'offre comme le second argument de http://www.rubydoc.info/github/sparklemotion/nokogiri/Nokogiri/XML/Node#xpath-instance_method

+0

'collect_namespaces' est une bonne chose à savoir – mikezter

Questions connexes