Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to retain order in XML Array to Hash conversion?

I'm trying to parse XML in Ruby using Nori, which internally uses Nokogiri. The XML has some tags repeated and the library parses repeated tags as Arrays and non-repeated tags as normal elements (Hash)

<nodes>
  <foo>
    <name>a</name>
  </foo>
  <bar>
    <name>b</name>
  </bar>
  <baz>
    <name>c</name>
  </baz>
  <foo>
    <name>d</name>
  </foo>
  <bar>
    <name>e</name>
  </bar>
</nodes>

is parsed as

{nodes: {
  foo: [{name: "a"}, {name: "d"}],
  bar: [{name: "b"}, {name: "e"}],
  baz: {name: "c"}
}}

How do i retain the order of elements in the resulting hash like the output below?

{nodes: [
      {foo: {name: "a"}}, 
      {bar: {name: "b"}},
      {baz: {name: "c"}},
      {foo: {name: "d"}},
      {bar: {name: "e"}},
    ]}

(This may be a library specific question. But the intention is to know if anyone has faced a similar issue and how to parse it correctly)

like image 242
Sathish Avatar asked Nov 22 '25 12:11

Sathish


1 Answers

Nori can't do this on its own. What you can do is tune the Nori output like this:

input = {nodes: {
  foo: [{name: "a"}, {name: "d"}],
  bar: [{name: "b"}, {name: "e"}],
  baz: {name: "c"}
}}

def unfurl(hash)
  out=[]
  hash.each_pair{|k,v|
    case v
    when Array
      v.each{|item|
        out << {k => item}
      }
    else
      out << {k => v}
    end
  }
  return out
end

output = {:nodes => unfurl(input[:nodes])}

puts output.inspect

This prints the output that the original question requested which is different than the XML order:

{nodes: [
  {foo: {name: "a"}}, 
  {foo: {name: "d"}},
  {bar: {name: "b"}},
  {bar: {name: "e"}},
  {baz: {name: "c"}},
]}
like image 78
joelparkerhenderson Avatar answered Nov 24 '25 06:11

joelparkerhenderson



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!