2013-02-26 98 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