Как я могу заставить Нокогири понять мои пространства имен? - PullRequest
5 голосов
/ 08 мая 2009

У меня есть следующий XML-документ:

<samlp:LogoutRequest ID="123456789" Version="2.0" IssueInstant="200904051217">
  <saml:NameID>@NOT_USED@</saml:NameID>
  <samlp:SessionIndex>abcdefg</samlp:SessionIndex>
</samlp:LogoutRequest>

Я бы хотел извлечь из него содержимое SessionIndex (то есть 'abcdefg'). Я пробовал это:

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, но это ничего не меняет.

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

Ответы [ 2 ]

9 голосов
/ 20 августа 2010

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

  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

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

    OR

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

6 голосов
/ 08 мая 2009

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

doc.xpath(XPATH_QUERY)
...