Как обрабатывать элементы 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
вместо.