2010-12-13 50 views
0

這是我的問題。我正在調用返回幾個包含不同值的相同節點的服務。我需要從這些節點獲取GUID值,並將它們作爲變量存儲在我的腳本中以供稍後使用。我從服務寫的XML的Ruby 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,並將每個請求的所有值拉回來,並將它們放入一個我可以映射到我的代碼中的數組中。我的問題是,如果你有這個XML塊,你需要將GUID和GUID2作爲變量存儲在Ruby腳本中,你會建議用什麼來解析它,並且你有一個讀取它的例子並剝離它值?

ROXML,REXML,Nokogiri,Regex ???

我感謝您的幫助!
〜Regards Uninspired

+0

除非XML是完全控制範圍之內,是簡單,不要使用正則表達式。像Nokogiri這樣的解析器使用起來非常簡單,而且更加健壯。想象一下,如果你的XML從一個漂亮的打印/縮進格式變成一行上的所有東西,並且你使用的是正則表達式,會發生什麼。解析器不會在意。 – 2010-12-14 00:05:03

回答

4

當然,使用XML解析庫!我能想到的手動做的唯一原因是爲了避免gem依賴。至於圖書館,這是非常主觀的,但我建議Nokogiri:快速,簡潔和強大。

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

這工作!謝謝!! – r3nrut 2010-12-14 16:17:14

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字符串,而不是一個文件英寸你將不得不換的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> 
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"] 
+0

爲什麼你在第一個例子中使用注入而不是地圖? – tokland 2010-12-14 08:02:26

+0

這只是完成它的一種不同的方式。就像他們說的那樣,「有一種方法可以讓貓變皮膚。」 – 2010-12-14 08:05:30