2012-08-13 25 views
6
ben gibi iç içe karma birçok düzeyine sahip

: Ben xml.send denedi bukullanarak XML iç içe karma dönüştürme Nokogiri

<foo>bar</foo> 
<foo1> 
    <foo2>bar2</foo2> 
    <foo3>bar3</foo3> 
    <foo4> 
     <foo5>bar5</foo5> 
    </foo4> 
</foo1> 

?: gibi bir XML haline çevirebiliriz nasıl

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

yöntem, ancak yukarıdaki iç içe geçmiş karmayı şu şekilde dönüştürür:

<foo1 foo3="bar3" foo4="foo5bar5" foo2="bar2"/> 
<foo>bar</foo> 
+0

sadece ekolojik – ecoologic

+0

Teşekkür hash.to_xml yapabileceği, ama onları çevreleyen etiketine sahip .. ben bunları istemiyorum. Dize manipülasyonları yerine bunları oluşturmak için düz bir yol var mı? – Hari

cevap

8

Bu nasıl olur? Kabul

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

h.to_xml 
#=> "<foo>bar</foo><foo1><foo2>bar2</foo2><foo3>bar3</foo3><foo4><foo5>bar5</foo5></foo4></foo1>" 
+0

Müthiş kodlama. teşekkürler :) – Hari

+0

Harita ve bitiş.join burada ne olduğunu açıklayabilir misiniz ??? – Hari

+1

Çok şık bir çözüm. –

3

temiz bir çözümdür, ancak aşağıda gerçekten 'kullanım' Nokogiri özellikleri için özel kargo ile bir Hash XML oluşturmak için kapsamaz:

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'}} 
       ] 
      } 
    }) 

Ve sonuç XML çıktı:

raylar içinde
<?xml version="1.0"?> 
<myroot> 
    <num>99</num> 
    <title>something witty</title> 
    <nested foo="bar" hello="world"> 
    <total>99</total> 
    <total>98</total> 
    </nested> 
    <anothernest foo="bar" hello="world"> 
    <date>today</date> 
    <date foo="blhjkldsaf"> 
     <day>23</day> 
     <month>Dec</month> 
     <year> 
     <y>1999</y> 
     <c>21</c> 
     </year> 
    </date> 
    </anothernest> 
</myroot> 


<?xml version="1.0"?> 
<root> 
    <num>99</num> 
    <title>something witty</title> 
    <nested foo="bar" hello="world"> 
    <total>99</total> 
    <total>98</total> 
    </nested> 
    <anothernest foo="bar" hello="world"> 
    <date>today</date> 
    <date foo="blhjkldsaf"> 
     <day>23</day> 
     <day>24</day> 
     <month>Dec</month> 
     <year> 
     <y>1999</y> 
     <c>21</c> 
     </year> 
    </date> 
    </anothernest> 
</root> 
İlgili konular