2009-05-08 6 views
5

У меня есть следующий XML-документ:Как заставить Нокигири понять мои пространства имен?

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

Я хотел бы получить содержание SessionIndex (то есть «АБВГДЕЖ») из него. Я попытался это:

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) 

, но я получаю следующие ошибки:

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 

Я попытался добавить пространство имен в запросе XPath, но это ничего не меняет.

Почему я не могу убедить Нокогири в том, что пространства имен действительны?

ответ

6

Это не похоже, что пространства имен в этом документе правильно объявлены - в корневом узле должны быть атрибуты xmlns:samlp и xmlns:saml. В подобных случаях, Nokogiri по существу игнорирует пространство имен (поскольку он не может сопоставить их с URI, или урн), поэтому ваш XPath работает, если вы удалите их, то есть

doc.xpath(XPATH_QUERY) 
+0

Это, кажется, чтобы дать мне ту же ошибку ... в некоторых ситуациях. Выполнение этого буквально в irb отлично работает, но мои спецификации все еще взрываются. Гарр. –

+0

Получил! Nokogiri возвращает узел «error», который обертывает найденный узел, но он _really_did_find_the_node_! –

9

Я вижу два различных варианта для вас:

  1. Удалить все пространство имен

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

    перебором способ сделать это. Может привести к проблемам, когда есть конфликты пространства имен.

  2. Использование collect_namespaces

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

    гораздо лучшее решение A. Вы можете использовать это один раз для идентификации пространств имен (например, irb) и их жесткого кода.

    ИЛИ

    Используйте его во время выполнения, и поставить его в качестве второго аргумента http://www.rubydoc.info/github/sparklemotion/nokogiri/Nokogiri/XML/Node#xpath-instance_method

+0

'collect_namespaces' - хорошая вещь, чтобы знать – mikezter