使用nokogiri将嵌套哈希转换为XML

我有很多级别的嵌套哈希,如:

{ :foo => 'bar', :foo1 => { :foo2 => 'bar2', :foo3 => 'bar3', :foo4 => { :foo5 => 'bar5' }}} 

我怎样才能将它们转换成这样的XML?:

 bar  bar2 bar3  bar5   

我已经尝试了xml.send方法,但它将上面嵌套的哈希转换为:

  bar 

这个怎么样?

 class Hash def to_xml  map do |k, v|   text = Hash === v ? v.to_xml : v   "<%s>%s" % [k, text, k]  end.join end end h.to_xml #=> "barbar2bar3bar5" 

接受是一个干净的解决方案,但下面确实“使用”Nokogiri从Hash构造XML并对属性进行特殊处理:

 require 'nokogiri' def generate_xml(data, parent = false, opt = {}) return if data.to_s.empty? return unless data.is_a?(Hash) unless parent # assume that if the hash has a single key that it should be the root root, data = (data.length == 1) ? data.shift : ["root", data] builder = Nokogiri::XML::Builder.new(opt) do |xml| xml.send(root) { generate_xml(data, xml) } end return builder.to_xml end data.each { |label, value| if value.is_a?(Hash) attrs = value.fetch('@attributes', {}) # also passing 'text' as a key makes nokogiri do the same thing text = value.fetch('@text', '') parent.send(label, attrs, text) { value.delete('@attributes') value.delete('@text') generate_xml(value, parent) } elsif value.is_a?(Array) value.each { |el| # lets trick the above into firing so we do not need to rewrite the checks el = {label => el} generate_xml(el, parent) } else parent.send(label, value) end } end puts generate_xml( {'myroot' => { 'num' => 99, 'title' => 'something witty', 'nested' => { 'total' => [99, 98], '@attributes' => {'foo' => 'bar', 'hello' => 'world'}}, 'anothernest' => { '@attributes' => {'foo' => 'bar', 'hello' => 'world'}, 'date' => [ 'today', {'day' => 23, 'month' => 'Dec', 'year' => {'y' => 1999, 'c' => 21}, '@attributes' => {'foo' => 'blhjkldsaf'}} ] } }}) puts puts puts generate_xml({ 'num' => 99, 'title' => 'something witty', 'nested' => { 'total' => [99, 98], '@attributes' => {'foo' => 'bar', 'hello' => 'world'}}, 'anothernest' => { '@attributes' => {'foo' => 'bar', 'hello' => 'world'}, 'date' => [ 'today', {'day' => [23,24], 'month' => 'Dec', 'year' => {'y' => 1999, 'c' => 21}, '@attributes' => {'foo' => 'blhjkldsaf'}} ] } }) 

结果XML输出:

   99 something witty  99 98   today  23 Dec  1999 21       99 something witty  99 98   today  23 24 Dec  1999 21