Как заставить Nokogiri разрешать ссылки XPath при разборе XML? - PullRequest
1 голос
/ 29 января 2011

Много было написано о Нокогири с точки зрения чтения XML с использованием XPath.Однако как насчет использования Nokogiri с XML, содержащим ссылки XPath.

В этом примере xml содержит ссылку XPath:

<elements>
 <element>
  <location>
   <longitude>...
   <latitude>...
  </location>
 </element>
 <element>
  <location reference="../../element/location"/>
 </element>
</elements>

Поскольку оба элемента местоположения равны, только первый элементподробно описано.Второй просто ссылается на первый.

Используя Nokogiri, xml.xpath ('// location') возвращает два экземпляра узла, как и ожидалось.Первый узел содержит все дочерние узлы.Вторая только ссылка в качестве атрибута экземпляра второго узла.

Хорошо, если я хочу запросить все значения долготы, я бы сделал xml.xpath ('// location / longitude') .Это возвращает только один экземпляр узла.Однако, поскольку на самом деле есть два элемента типа "долгота", я ожидал получить два экземпляра узла, ожидая, что Nokogiri разрешит ссылки XPath ...

Как мне достичь этого с помощью Nokogiri?

Ответы [ 2 ]

1 голос
/ 29 января 2011

Вы можете собрать узлы местоположения, которые имеют фактические значения (нереферентные узлы), а затем собрать все ссылки отдельно, как показано в следующем фрагменте:

require 'nokogiri'

xml = <<End
<elements>
 <element>
  <location>
   <longitude>45</longitude>
   <latitude>-70</latitude>
  </location>
 </element>
 <element>
  <location reference="../../element/location"/>
 </element>
</element>
End

doc = Nokogiri::XML(xml)

#Collect all the explicit longitudes
longitudes = doc.search('//location[not(@reference)]/longitude').map(&:text)

#Follow references to longitudes
doc.search('//location[@reference]').each do |location|
  reference = location.attribute('reference')
  longitudes << location.xpath("#{reference}/longitude").text
end

puts longitudes #=> ["45", "45"]

Вы можете использовать эту технику для извлечения любой необходимой вам информации.

0 голосов
/ 29 января 2011

Вы не предоставили никакой подсказки, как второй элемент location ссылается на первый.

Даже если бы этот механизм был известен , и мы смогли указать его в выражении XPath для выбора ссылочного элемента location, выбранные два узла longitude были бы идентичны .

Когда выражение XPath вычисляется, оно всегда возвращает набор узлов - то есть, если один и тот же узел выбран более одного раза, он представляется только один раз в выборе результат - набор не содержит повторяющихся элементов.

Вот почему элемент longitude будет отображаться только один раз при выделении, даже если он был выбран дважды.

Вот пример ;

<a>
 <b>
   <c/>
 </b>
</a>

Выражение XPath :

/ a / * | //c/..

выбирает только один элемент b - не два идентичных элемента b.

...