Как заставить Nokogiri понимать мои пространства имен?

У меня есть следующий 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, но это ничего не меняет.

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


person James A. Rosen    schedule 08.05.2009    source источник


Ответы (2)


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

doc.xpath(XPATH_QUERY)
person Greg Campbell    schedule 08.05.2009
comment
Кажется, это дает мне те же ошибки ... в некоторых ситуациях. Выполнение этого буквально в irb работает нормально, но выполнение моих спецификаций все еще взрывается. Гарр. - person James A. Rosen; 09.05.2009
comment
Понятно! Nokogiri возвращает узел ошибки, который заключает в себе найденный узел, но это действительно_did_find_the_node! - person James A. Rosen; 09.05.2009

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

  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

person Jamie Cobbett    schedule 20.08.2010