【问题标题】:Parsing XML using Nokogiri使用 Nokogiri 解析 XML
【发布时间】:2013-02-28 02:43:34
【问题描述】:

我正在使用 rest-client 从另一个网站返回 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,所以,我知道 rest-client 正在工作,但我不知道如何访问解析的 XML。


更新1:

我能够使用以下方法从 XML 标头中获取 creationDateTime。但是,我仍然无法获得 SEED 值:

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

【问题讨论】:

  • 请不要把所有这些逻辑都放在你的视野中。
  • Mark - 它应该放在控制器还是模型中? (抱歉 - 我是新手)
  • @Reddirt 控制器。从控制器中的 XML 中提取您想要的片段,然后将它们放置在您希望在视图中看到的位置。

标签: ruby-on-rails ruby nokogiri


【解决方案1】:

您的代码中有几处错误,所以我会这样做:

从这段代码开始:

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 访问器,并返回一个 NodeSet,它就像一个节点数组:

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::Element”,这是 Nokogiri 描述节点的方式,而不是来自 xpath(AKA search)的 NodeSet(AKA 数组)。

拥有节点后,获取文本很简单:

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

在给定小的 XML sn-p 的情况下,我如何获取这两个值并将它们分配给两个变量:

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

【讨论】:

    【解决方案2】:

    您的最后一行代码 puts doc.xpath("//SEED").inner_text 应该可以工作。真正的 XML 是否有任何名称空间?如果是,请尝试以下操作:puts doc.css("SEED").inner_text

    【讨论】:

    • 使用xpathcss 可以处理这样一个简单的XML 文件,但如果&lt;SEED&gt; 标记多次出现,则会返回意外结果而失败。
    猜你喜欢
    • 2013-03-21
    • 1970-01-01
    • 1970-01-01
    • 2013-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多