RubyXML:为现有XML提供唯一的节点来读取

RubyXML:为现有XML提供唯一的节点来读取,ruby,xml,xml-parsing,Ruby,Xml,Xml Parsing,这是我的问题。我正在调用一个服务,该服务返回几个包含不同值的相同节点。我需要从这些节点获取GUID值,并将它们作为变量存储在脚本中以供以后使用 我从服务中编写的XML示例: <ShippingMethod> <Description>Description Goes Here</Description> <HandlingCharge>16.98</HandlingCharge> <ShippingMeth

这是我的问题。我正在调用一个服务,该服务返回几个包含不同值的相同节点。我需要从这些节点获取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>

这里有描述
16.98
指南
通宵快递
描述2在这里
19.98
指南2
通宵快递
我在每个请求中都有几个,它们是动态的。我不想基于我目前拥有的值,用正则表达式把它切碎。那是黑的,以后会咬我的。此时,我唯一感兴趣的事情是读取此XML,并提取每个请求的所有值,然后将它们放入一个数组中,我可以在代码中映射该数组。我的问题是,如果您有这段XML,并且需要将GUID和GUID2作为变量存储在Ruby脚本中,您会建议使用什么来解析它?您是否有一个读取它并剥离值的示例

ROXML,REXML,Nokogiri,Regex

我感谢你的帮助
~z~我过去曾成功地完成过类似的任务。以下脚本将提取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字符串而不是文件。您必须将xml片段包装在单个根元素中,以使其成为格式良好的xml,然后REXML才能对其进行解析:

<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>

这里有描述
16.98
指南
通宵快递
描述2在这里
19.98
指南2
通宵快递

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

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

以下是我的一些方法:

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"]
需要“nokogiri”
xml='1〕
这里有描述
16.98
指南
通宵快递
描述2在这里
19.98
指南2
通宵快递
'
doc=Nokogiri::XML(XML)
css('ShippingMethodId').inject([]){m,a | m[“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”]

除非XML完全在您的控制范围内且非常简单,否则不要使用正则表达式。像Nokogiri这样的解析器使用起来非常简单,而且更加健壮。想象一下,如果您的XML从漂亮的打印/缩进格式变为一行中的所有格式,并且您正在使用正则表达式,会发生什么情况。解析器不会在意。为什么在第一个正则表达式中使用inject充足而不是地图?这只是一种不同的实现方式。就像他们说的,“剥猫皮的方法不止一种。”