Как обрабатывать элементы XML, которые могут или не могут быть повторены с использованием объекта XML

Я использую гем XML-объекта для обработки XML. Определенные элементы в XML, который мы получаем, могут повторяться или не повторяться. Когда они появляются только один раз, xml-объект связывает их как свойство, не являющееся массивом, но когда они появляются более одного раза, они связываются как массив. Я бы предпочел обращаться с ними так, как будто они всегда связаны как массив. Это должно объяснить, о чем я говорю:

!/usr/bin/env ruby
require 'rubygems'
require 'xml-object'

XML_ONE = <<END
<foo>
  <bar baz="123">abc</bar>
</foo>
END

foo = XMLObject.new(XML_ONE)
puts foo.bar
puts foo.bar.baz

XML_TWO = <<END
<foo>
  <bar baz="123">abc</bar>
  <bar baz="456">def</bar>
</foo>
END

foo = XMLObject.new(XML_TWO)
puts foo.bar[0]
puts foo.bar[0].baz

То, что я хотел бы сделать, это обработать XML в форме XML_ONE идентично XML в форме XML_TWO. Я пытался сделать это:

puts [*foo.bar][0]
puts foo.bar.to_a[0]
puts [*foo.bar][0].baz
puts foo.bar.to_a[0].baz

Первые две строки выведите "abc". Вторые два терпят неудачу, жалуясь, что нет никакого метода "baz" на "abc". Из того, что я могу сказать, когда результат "foo.bar" преобразуется в массив, этот массив содержит "простую" строку, а не строку с инструментами, возвращаемую "foo.bar", которая имеет метод "baz".

Какие-нибудь мысли?

1 ответ

Решение

Я бы попытался использовать что-то другое для разбора XML. После небольшой игры с гемом xml-object кажется, что он не соответствует типу возвращаемых объектов. я хотел бы использовать Nokogiri вместо. Мне удалось получить поведение, которое вы пытались с этим кодом:

#!/usr/bin/env ruby
require 'rubygems'
require 'xml-object'
require 'nokogiri'

XML_ONE = <<END
<foo>
  <bar baz="123">abc</bar>
</foo>
END

XML_TWO = <<END
<foo>
  <bar baz="123">abc</bar>
  <bar baz="456">def</bar>
</foo>
END

xml1 = Nokogiri::XML(XML_ONE)
xml2 = Nokogiri::XML(XML_TWO)

puts xml1.xpath('/foo/bar/@baz')[0]
puts xml2.xpath('/foo/bar/@baz')[1]

Результаты:

123
456

В Nokogiri есть аналогичная функциональность для XMLObject, через Nokogiri::Slop, но это было так же противоречиво, как XMLObject, поэтому я решил использовать Nokogiri::XML().xpath вместо.

Другие вопросы по тегам