如何在Ruby中访问和读取xml标记及其内容

时间:2011-04-27 21:34:28

标签: ruby xml

在一个课程中,我们的老师给了我们一个项目,将CSV转换为XML格式,再次从XML转换为CSV,并告诉我们在Python和Ruby之间进行选择。我更喜欢Ruby,因为它对我来说似乎更容易理解。

我已完成第一部分,从CSV转换为XML,并且工作正常。但是当我想从XML转换为CSV时,我的代码可以工作,但仅适用于特定的XML文件。我想让它适用于任何XML文件。

这是我的XML,我不会把它全部放在一边因为它很大:

<?xml version="1.0"?>
<records>
   <company>
     <id>p1</id>
     <name>Skoda</name>
     <price>10000</price>
     <stock>4</stock>
     <country>Czech Republic</country>
  </company>
  <company>
     <id>p2</id>
     <name>Mercedes</name>
     <price>50000</price>
     <stock>5</stock>
     <country>Germany</country>
  </company>
  <company>
     <id>p3</id>
     <name>Alfa Romeo</name>
     <price>18000</price>
     <stock>19</stock>
     <country>Italy</country>
  </company>
  <company>
     <id>p4</id>
     <name>Fiat</name>
     <price>1500</price>
     <stock>15000</stock>
     <country>Italy</country>
  </company>
</records>

我的用于XML到CSV转换的Ruby代码是:

xmlinputfile = gets.chomp
print "\n"
csvoutputfile = gets.chomp
print "\n"
puts "Writing CSV..."
print "\n"
xml_file = File.open(xmlinputfile, "r")
xml = REXML::Document.new( xml_file )
csv_file = File.new(csvoutputfile, "w") 
xml.elements.each("records") do |e|
  e.elements.each("company") do |f|
    csv_file.puts f.elements['id'].text + "," + f.elements['name'].text + "," 
      + f.elements['price'].text + "," + 
      f.elements['stock'].text + ","+ f.elements['country'].text + ","
  end
end
print "Job Done !!! \n"
puts "Contents of #{xmlinputfile} were written in CSV format to #{csvoutputfile}.\n\n"

问题是这个Ruby代码只能用于上面的XML,而不能用于任何其他XML代码,因为我找不到让代码自己读取XML标签的方法,并放置他们的内容为CSV格式。在上面的代码中,我将自己的XML标记作为

中的字符串参数
  

f.elements [ 'XML_TAG']

因此它可以采用其内容并以CSV格式写入。但这并不好,因为当我使用另外一个带有更多标签的XML时,它将不起作用。

我想要做的是,当我插入xml输入文件的名称时,代码可以找到xml中有多少个标签并将其内容放入CSV格式。

请它非常重要。我必须在3天内完成这个项目,我几乎试了一个星期,没有做任何事情。你们是我的最后一次机会!

1 个答案:

答案 0 :(得分:0)

require 'nokogiri' # http://nokogiri.org  aka  gem install nokogiri
xmldoc = Nokogiri::XML(IO.read("records.xml"))

rows = []
xmldoc.xpath('/*/*').each do |row_xml|
  row_values = []
  rows << row_values
  row_xml.xpath('./*').each do |field|
    row_values << field.text
  end
end

require 'pp'
pp rows
#=> [["p1", "Skoda", "10000", "4", "Czech Republic"],
#=>  ["p2", "Mercedes", "50000", "5", "Germany"],
#=>  ["p3", "Alfa Romeo", "18000", "19", "Italy"],
#=>  ["p4", "Fiat", "1500", "15000", "Italy"]]

或者更简洁地说,您可以通过以下方式获得相同的结果:

rows = xmldoc.xpath('/*/*').map{ |row| row.xpath('./*').map(&:text) }

如果你想要'列'的名字:

columns = xmldoc.xpath('/*/*[position()=1]/*').map(&:name)
#=> ["id", "name", "price", "stock", "country"]