Почему Nokogiri xpath не нравится объявления xmlns - PullRequest
23 голосов
/ 15 ноября 2009

Я использую Nokogiri :: XML для анализа ответов от Amazon SimpleDB. Ответ выглядит примерно так:

<SelectResponse xmlns="http://sdb.amazonaws.com/doc/2007-11-07/">
  <SelectResult>
    <Item>
      <Attribute><Name>Foo</Name><Value>42</Value></Attribute>
      <Attribute><Name>Bar</Name><Value>XYZ</Value></Attribute>
    </Item>
  </SelectResult>
</SelectResponse>

Если я просто передам ответ Нокогири, все запросы XPath (например, doc/"//Item/Attribute[Name='Foo']/Value") возвращают пустой массив. Но если я удаляю атрибут xmlns из тега SelectResponse, он отлично работает.

Есть ли еще что-то, что мне нужно сделать, чтобы учесть объявление пространства имен? Этот обходной путь выглядит ужасно, как хак.

Ответы [ 2 ]

32 голосов
/ 15 ноября 2009

Этот запрос XPath ищет элементы, которые не находятся ни в одном пространстве имен. Вам нужно сообщить вашему процессору XPath, что вы ищете элементы в пространстве имен http://sdb.amazonaws.com/doc/2007-11-07/

Один из способов сделать это с помощью nokogiri - это:

doc = Nokogiri::XML.parse(...)
doc.xpath("//aws:Item/aws:Attribute[Name='Foo']/aws:Value", {"aws" => "http://sdb.amazonaws.com/doc/2007-11-07/"})
20 голосов
/ 10 мая 2010

Я нашел это действительно полезным для понимания того, что происходит: http://tenderlovemaking.com/2009/04/23/namespaces-in-xml.html

Обычно, если у вас вообще определено пространство имен (через xmlns=), вы должны использовать пространство имен в поиске xpath.

Итак, в вашем случае вы можете сделать одну из трех вещей:

  • Удалить атрибут xmlns из корня SearchResponse. В этом случае ваш оригинальный запрос xpath без пространства имен будет работать.
  • Используйте пространство имен по умолчанию в запросе xpath doc/"//xmlns:Item/xmlns:Attribute[xmlns:Name='Foo']/xmlns:Value"
  • Определите пользовательское пространство имен во втором аргументе вызова метода xpath и используйте его в своем запросе, как показано в решении hrnt выше
...