2009-05-08 9 views
5

tengo el siguiente documento XML:¿Cómo hago que Nokogiri comprenda mis espacios de nombres?

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

me gustaría obtener el contenido de la SessionIndex (es decir, 'abcdefg') fuera de ella. He intentado esto:

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) 

pero consigo los siguientes errores:

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 

He intentado añadir los espacios de nombres a la consulta XPath, pero eso no cambia nada.

¿Por qué no puedo convencer a Nokogiri de que los espacios de nombres son válidos?

Respuesta

6

No parece que los espacios de nombres en este documento estén declarados correctamente; deben existir los atributos xmlns:samlp y xmlns:saml en el nodo raíz. En casos como este, Nokogiri esencialmente ignora los espacios de nombres (ya que no les puede asignar a los URI o URN), por lo que su XPath funciona si se les quita, es decir

doc.xpath(XPATH_QUERY) 
+0

Eso me parece dar los mismos errores ... en algunas situaciones. Hacerlo literalmente en IRB funciona bien, pero ejecutar mis especificaciones todavía explota. Garr. –

+0

¡Entendido! Nokogiri devuelve un nodo de "error" que envuelve el nodo que encontró, ¡pero _really_did_find_the_node_! –

9

Veo dos opciones diferentes para usted:

  1. eliminar todos los espacios de nombres

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

    Bruto manera la fuerza de hacerlo. Podría provocar problemas cuando haya colisiones de espacios de nombres.

  2. Uso collect_namespaces

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

    Una solución mucho mejor. Puede usar esto una vez para identificar los espacios de nombres (por ejemplo, en irb) y codificarlos.

    O

    utilizarlo en tiempo de ejecución, y suministrarla como segundo argumento a http://www.rubydoc.info/github/sparklemotion/nokogiri/Nokogiri/XML/Node#xpath-instance_method

+0

'collect_namespaces' es bueno saber – mikezter

Cuestiones relacionadas