如何覆盖从哈希生成XML?

时间:2014-03-21 13:51:25

标签: ruby ruby-on-rails-3

我有这样的哈希:

{
  12776=>["Item", "01:Antique", "fabric"], 
  12777=>["Item", "02:Priceless", "porcelain"], 
  12740=>["Item", "01:Antique", "silver"]
}

我想生成XML,如:

<items>
  <item type="01:Antique", material="fabric">some other attribute</item>
  <item type="02:Priceless", material="porcelain">some other attribute</item>
  <item type="01:Antique", material="silver">some other attribute</item>
</items>

请证明这是可行的。

3 个答案:

答案 0 :(得分:2)

我肯定会建议使用像Nokogiri这样的宝石为你做这件事。这样的事情应该有效:

xml = Nokogiri::XML::Builder.new
xml.items do
  hash.values.each do |item_array|
    xml.item(type: item_array[1], material: item_array[2]) #some_other_attribute
  end
end

呈现此XML:

1.9.3-p484 :019 > puts xml.to_xml

<?xml version="1.0"?>
<items>
  <item type="01:Antique" material="fabric"/>
  <item type="02:Priceless" material="porcelain"/>
  <item type="01:Antique" material="silver"/>
</items>

答案 1 :(得分:1)

这看起来是正确的:

require 'nokogiri'

hash = {
  12776 => ["Item", "01:Antique", "fabric"], 
  12777 => ["Item", "02:Priceless", "porcelain"], 
  12740 => ["Item", "01:Antique", "silver"]
}

xml = Nokogiri::XML::Builder.new
xml.items do
  hash.each do |key, (_, _type, material)|
    xml.item(type: _type, material: material) {
      text "some_other_attribute"
    }
  end
end

puts xml.to_xml
# >> <?xml version="1.0"?>
# >> <items>
# >>   <item type="01:Antique" material="fabric">some_other_attribute</item>
# >>   <item type="02:Priceless" material="porcelain">some_other_attribute</item>
# >>   <item type="01:Antique" material="silver">some_other_attribute</item>
# >> </items>
  • 哈希each将键/值对发送到块中。
  • 使用(_, _type, material)将每个值的元素分配给变量。
  • _是一个黑洞变量(不是真的,但这足以让它以这种方式使用它),并吞下传递给它的值;实际上,它意味着“忽略”。
  • 我使用_type来避免与type混淆。 Ruby会很高兴,但我不会。

其余的应该是不言而喻的。

答案 2 :(得分:0)

脏的原始实现。如果需要,您可以尝试使用某些XML库(如Nokogiri)来操作XML生成。

hash = {
  12776=>["Item", "01:Antique", "fabric"], 
  12777=>["Item", "02:Priceless", "porcelain"], 
  12740=>["Item", "01:Antique", "silver"]
}

puts "<items>"

hash.sort_by{|k, _| k}.each do |_, array|
  puts %{  <item type="#{array[1]}" material="#{array[2]}">some other attribute</item>}
  # or maybe the following?
  #puts %{  <item type="#{array[1]}" material="#{array[2]}">#{array[3..-1].join(" ")}</item>}
end

puts "</items>"