0

I'm using the xml-object gem to process XML. Certain elements in the XML we receive may or may not be repeated. When they only appear once, xml-object binds them as a non-array property, but when they appear more than once they're bound as an array. I would prefer to treat them as if they were always bound as an array. This should explain what I'm talking about:

!/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

What I would like to do is process xml in the form of XML_ONE identically to xml of the form XML_TWO. I tried doing this:

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

The first two lines output "abc". The second two fail, complaining that there's no method "baz" on "abc". From what I can tell, when the result of "foo.bar" is coerced into an array, that array contains a "plain" string and not the instrumented string returned by "foo.bar", which has the method "baz".

Any thoughts?

jph
  • 1,943
  • 1
  • 27
  • 47

1 Answers1

0

I would try to use something different to parse the XML. After a bit of playing with the xml-object gem, it seems to lack consistency with the type of objects that it returns. I would use Nokogiri instead. I was able to get the behavior you were trying for with this code:

#!/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]

Results:

123
456

There is similar functionality to XMLObject in Nokogiri as well, via Nokogiri::Slop, but it was just as inconsistent as XMLObject, which is why I opted to use Nokogiri::XML().xpath instead.

Eugene
  • 4,641
  • 1
  • 21
  • 49
  • Thanks for the pointer. I'm not a whiz at xpath, so I was hoping to avoid it and deal purely at the object level. But you gotta do what you gotta do. – jph Mar 13 '12 at 16:44