2013-02-26 94 views
0

我正在使用rest-client從其他網站返回XML並試圖使用Nokogiri來解析它。 XML看起來像這樣:使用Nokogiri解析XML

<?xml version="1.0" encoding="UTF-8"?> ... 
<MXAUTOKESet> 
    <AUTOKEY> 
    <AUTOKEYID>27</AUTOKEYID> 
    <AUTOKEYNAME>WORKORDERNUM</AUTOKEYNAME> 
    <ORGID>xxxx</ORGID> 
    <PREFIX>12-</PREFIX> 
    <SEED>38979</SEED> 
    ... 

我想提取「PREFIX」和「SEED」數字。

我的看法代碼如下所示:

<% xml_data = RestClient.get "URL (sorry can't display it in this question)" %> 
<%= xml_doc = Nokogiri::XML(xml_data)%> 

第二行顯示在頁面上返回的XML,所以,我都知道了,客戶端的工作,但我不知道如何訪問解析XML。


UPDATE1:

我能得到creationDateTime出使用下面的XML頭的。但是,我還是不能讓種子值:

<%= doc = Nokogiri::XML(xml_data)%>  
<h4>Creation Date</h4> 
<% root = doc.root %> 
<%= root["creationDateTime"] %> 
<h4>SEED</h4> 
<%= seed = root.xpath("SEED").text %> 

<%= seed = doc.xpath("//SEED").inner_text %> 
+2

請不要把所有這些邏輯放在你的視野中。 – 2013-02-27 02:03:26

+0

馬克 - 它應該放在控制器還是模型中? (對不起 - 我是新手) – Reddirt 2013-02-27 15:18:26

+1

@Reddirt控制器。從控制器中的XML中提取所需的部分,然後將它們放在視圖中要查看它們的位置。 – Phrogz 2013-02-27 15:26:51

回答

2

有幾件事情錯在你的代碼,所以這裏就是我想要做的事情:

與此代碼開始:

require 'nokogiri' 

doc = Nokogiri::XML(<<EOT) 
<?xml version="1.0" encoding="UTF-8"?> 
<MXAUTOKESet> 
    <AUTOKEY> 
    <AUTOKEYID>27</AUTOKEYID> 
    <AUTOKEYNAME>WORKORDERNUM</AUTOKEYNAME> 
    <ORGID>xxxx</ORGID> 
    <PREFIX>12-</PREFIX> 
    <SEED>38979</SEED> 
EOT 

puts doc.to_xml 

我得到這個輸出,顯示出引入nokogiri做了一些修正,直至關閉打開的標籤,確保XML的合理正確大塊:

<?xml version="1.0" encoding="UTF-8"?> 
<MXAUTOKESet> 
    <AUTOKEY> 
    <AUTOKEYID>27</AUTOKEYID> 
    <AUTOKEYNAME>WORKORDERNUM</AUTOKEYNAME> 
    <ORGID>xxxx</ORGID> 
    <PREFIX>12-</PREFIX> 
    <SEED>38979</SEED> 
</AUTOKEY></MXAUTOKESet> 

xpath預計的XPath訪問,並返回一個節點集,這就好比是一個節點數組:

doc.xpath("//SEED").class 
=> Nokogiri::XML::NodeSet 
doc.xpath("//SEED") 
=> [#<Nokogiri::XML::Element:0x3fdf890e3208 name="SEED" children=[#<Nokogiri::XML::Text:0x3fdf890e3000 "38979">]>] 

的問題是,xpath,其css對應,將返回自己的目標的每一次出現,他們在文件中找到,這是不如果有兩個或更多「SEED」標籤,您需要什麼。相反,您想要atat_xpathat_css返回找到的第一個匹配項;我推薦使用at(或search)和CSS進行第一次測試,因爲它比XPath更易於理解。

轉換爲使用at和CSS:

doc.at("SEED").class 
=> Nokogiri::XML::Element 
doc.at("SEED") 
=> #<Nokogiri::XML::Element:0x3fdf890e3208 name="SEED" children=[#<Nokogiri::XML::Text:0x3fdf890e3000 "38979">]> 

注意doc.at("SEED")返回 「引入nokogiri :: XML ::元素」,這是引入nokogiri如何描述一個節點,而不是一個節點集(AKA陣列)從xpath(AKA search)。

獲取的文字很簡單,一旦你有節點:

doc.at("SEED").text 
=> "38979" 

以下是我想抓住這兩個值,並將其分配給兩個變量,鑑於小XML片段:

seed, prefix = %w[SEED PREFIX].map{ |t| doc.at(t).text } 
=> ["38979", "12-"] 
+0

doc.at(「SEED」)。text works !!!!!!!謝謝! – Reddirt 2013-02-27 14:40:45

1

你的代碼,puts doc.xpath("//SEED").inner_text最後一行,應該工作。真正的XML是否有任何命名空間?如果是的話,試試這個:puts doc.css("SEED").inner_text

+0

使用'xpath'和'css'可以在這樣一個簡單的XML文件上工作,但如果出現多個''標籤,它將返回意想不到的結果。 – 2013-02-27 06:55:15