Ruby XML:提供要读取的现有XML唯一节点

时间:2010-12-13 21:19:42

标签: ruby xml xml-parsing

这是我的问题。我正在调用一个返回几个包含不同值的相同节点的服务。我需要从这些节点获取GUID值,并将它们作为变量存储在我的脚本中以供稍后使用。

我从服务中写的XML示例:

<ShippingMethod>
    <Description>Description Goes Here</Description>
    <HandlingCharge>16.98</HandlingCharge>
    <ShippingMethodId>GUID</ShippingMethodId>
    <ShippingMethodName>Express Overnight</ShippingMethodName>
  </ShippingMethod>
<ShippingMethod>
    <Description>Description2 Goes Here</Description>
    <HandlingCharge>19.98</HandlingCharge>
    <ShippingMethodId>GUID2</ShippingMethodId>
    <ShippingMethodName>More Express Overnight</ShippingMethodName>
  </ShippingMethod>

我有几个这样的请求,它们是动态的。我不想根据我目前的值使用正则表达式来修改它。那太苛刻了,以后会咬我的。在这一点上我唯一感兴趣的是读取这个XML并将每个请求的所有值拉回来并将它们放入一个我可以在我的代码中映射的数组中。我的问题是,如果你有这个XML块,你需要将GUID和GUID2作为变量存储在Ruby脚本中,你建议使用什么来解析它,你是否有一个读取它并剥离它的例子值?

ROXML,REXML,Nokogiri,Regex ???

感谢您的帮助! 〜问候没有灵感

3 个答案:

答案 0 :(得分:4)

当然,使用XML解析库!我能想到手动操作的唯一原因是避免了gem依赖。至于图书馆,这是非常主观的,但我推荐Nokogiri:快速,简洁和强大。

require 'nokogiri'
doc = Nokogiri::XML.parse(xml_string)
doc.css("ShippingMethod ShippingMethodId").map(&:text) # ["GUID", "GUID2"]

答案 1 :(得分:2)

我过去曾成功使用REXML这样的任务。以下脚本将提取GUID值:

require "rexml/document"

doc = REXML::Document.new File.open('doc.xml')
guids = doc.root.get_elements('//ShippingMethodId').map { |element| element.get_text }

假设文件名为“doc.xml”,或者您只能传入XML字符串而不是文件。在将REXML解析之前,您必须将xml片段包装在单个根元素中以使其格式良好:

<Root>
  <ShippingMethod>
    <Description>Description Goes Here</Description>
    <HandlingCharge>16.98</HandlingCharge>
    <ShippingMethodId>GUID</ShippingMethodId>
    <ShippingMethodName>Express Overnight</ShippingMethodName>
  </ShippingMethod>
  <ShippingMethod>
    <Description>Description2 Goes Here</Description>
    <HandlingCharge>19.98</HandlingCharge>
    <ShippingMethodId>GUID2</ShippingMethodId>
    <ShippingMethodName>More Express Overnight</ShippingMethodName>
  </ShippingMethod>
</Root>

答案 2 :(得分:2)

以下是我的一些方法:

require 'nokogiri'

xml = '<xml><ShippingMethod>
    <Description>Description Goes Here</Description>
    <HandlingCharge>16.98</HandlingCharge>
    <ShippingMethodId>GUID</ShippingMethodId>
    <ShippingMethodName>Express Overnight</ShippingMethodName>
</ShippingMethod>
<ShippingMethod>
    <Description>Description2 Goes Here</Description>
    <HandlingCharge>19.98</HandlingCharge>
    <ShippingMethodId>GUID2</ShippingMethodId>
    <ShippingMethodName>More Express Overnight</ShippingMethodName>
</ShippingMethod></xml>
'
doc = Nokogiri::XML(xml)
doc.css('ShippingMethodId').inject([]){ |m,a| m << a.text } # => ["GUID", "GUID2"]
(doc / '//ShippingMethodId').map{ |n| n.text }              # => ["GUID", "GUID2"]
doc.search('//ShippingMethodId').map(&:text)                # => ["GUID", "GUID2"]
doc.search('//ShippingMethodId/text()').map{ |n| n.text }   # => ["GUID", "GUID2"]
doc.search('//ShippingMethodId/text()').map(&:to_s)         # => ["GUID", "GUID2"]