54

我对使用 XML 很陌生,但我的腿上刚好有一个需求。我得到了一个通常的(对我来说)XML 格式。标签中有冒号。

<THING1:things type="Container">
  <PART1:Id type="Property">1234</PART1:Id>
  <PART1:Name type="Property">The Name</PART1:Name>
</THING1:things>

它是一个大文件,它的内容远不止于此,但我希望这种格式对某些人来说是熟悉的。有谁知道处理这种 XML 文档的方法?

我宁愿不只是写一种蛮力的方式来解析文本,但我似乎无法在 REXML 或 Hpricot 方面取得任何进展,我怀疑这是由于这些不寻常的标签。

我的红宝石代码:

    require 'hpricot'
    xml = File.open( "myfile.xml" )

    doc = Hpricot::XML( xml )

   (doc/:things).each do |thg|
     [ 'Id', 'Name' ].each do |el|
       puts "#{el}: #{thg.at(el).innerHTML}"
     end
   end

...刚刚从:http ://railstips.org/blog/archives/2006/12/09/parsing-xml-with-hpricot/

我想我可以从这里找出一些东西,但是这段代码什么也没返回。它不会出错。它只是返回。

4

2 回答 2

85

正如@pguardiario 所提到的,Nokogiri是事实上的 XML 和 HTML 解析库。如果你想在你的例子中打印出IdandName值,你可以这样做:

require 'nokogiri'

xml_str = <<EOF
<THING1:things type="Container">
  <PART1:Id type="Property">1234</PART1:Id>
  <PART1:Name type="Property">The Name</PART1:Name>
</THING1:things>
EOF

doc = Nokogiri::XML(xml_str)

thing = doc.at_xpath('//things')
puts "ID   = " + thing.at_xpath('//Id').content
puts "Name = " + thing.at_xpath('//Name').content

几点注意事项:

  • at_xpath是为了匹配一件事。如果你知道你有多个项目,你想使用它xpath
  • 根据您的文档,命名空间可能会出现问题,因此调用doc.remove_namespaces!会有所帮助(请参阅此答案以进行简短讨论)。
  • 您可以使用这些css方法,而不是xpath如果您对这些方法更满意。
  • 一定要玩弄这个irbpry调查方法。

资源

更新

要处理多个项目,您需要一个根元素,并且需要//xpath查询中删除 。

require 'nokogiri'

xml_str = <<EOF
<root>
  <THING1:things type="Container">
    <PART1:Id type="Property">1234</PART1:Id>
    <PART1:Name type="Property">The Name1</PART1:Name>
  </THING1:things>
  <THING2:things type="Container">
    <PART2:Id type="Property">2234</PART2:Id>
    <PART2:Name type="Property">The Name2</PART2:Name>
  </THING2:things>
</root>
EOF

doc = Nokogiri::XML(xml_str)
doc.xpath('//things').each do |thing|
  puts "ID   = " + thing.at_xpath('Id').content
  puts "Name = " + thing.at_xpath('Name').content
end

这会给你:

Id   = 1234
Name = The Name1

ID   = 2234
Name = The Name2

如果您更熟悉 CSS 选择器,则可以使用这段几乎相同的代码:

doc.css('things').each do |thing|
  puts "ID   = " + thing.at_css('Id').content
  puts "Name = " + thing.at_css('Name').content
end
于 2012-06-27T05:29:08.417 回答
44

如果在 Rails 环境中,Hash对象被扩展并且可以利用该方法from_xml

xml = File.open("myfile.xml")
data = Hash.from_xml(xml)
于 2016-05-17T21:48:19.273 回答