无法通过nokogiri解析的xml中的元素的属性名称找到值

时间:2014-09-25 21:40:16

标签: ruby xml nokogiri

我有以下XML:

<cpe-list>  
  <cpe-item name="cpe:/a:1024cms:1024_cms:0.7">
    <title xml:lang="en-US">1024cms.org 1024 CMS 0.7</title>
    <meta:item-metadata nvd-id="121218" status="DRAFT" modification-date="2010-12-14T19:38:32.197Z"/>
  </cpe-item>
  <cpe-item name="cpe:/a:1024cms:1024_cms:1.2.5">
    <title xml:lang="en-US">1024cms.org 1024 CMS 1.2.5</title>
    <meta:item-metadata nvd-id="121219" status="DRAFT" modification-date="2010-12-14T19:38:32.240Z"/>
  </cpe-item>
    <cpe-item name="cpe:/h:cisco:ips_4240">
    <title xml:lang="ja-JP">JAPAN IPS 4240 Sensor</title>
    <title xml:lang="en-US">EN Cisco IPS 4240 Sensor</title>
    <meta:item-metadata nvd-id="138255" status="DRAFT" modification-date="2011-01-12T14:36:11.990Z"/>
  </cpe-item>
</cpe-list>

我需要保存'title'字段的值,只使用lang = en-US属性。所以我试图通过以下方式获得“EN Cisco IPS 4240传感器”:

doc.search("//title[@lang='en-US']")

返回

 => [] 

请告知如何正确获取这些字段的值。

2 个答案:

答案 0 :(得分:2)

该属性是命名空间(它是xml:lang,而不仅仅是lang),因此您需要在搜索中包含命名空间:

doc.search("//title[@xml:lang='en-US']")

我只是在本地尝试了这个,它返回所有三个<title xml:lang="en-US">元素。要获取每个文本,只需在每个文本上调用text,或使用map

doc.search("//title[@xml:lang='en-US']").map(&:text)
# => [ "1024cms.org 1024 CMS 0.7",
#      "1024cms.org 1024 CMS 1.2.5",
#      "EN Cisco IPS 4240 Sensor" ]

答案 1 :(得分:0)

Nokogiri支持CSS选择器,所以我会这样做:

require 'nokogiri'

xml = '<cpe-list>  
  <cpe-item name="cpe:/a:1024cms:1024_cms:0.7">
    <title xml:lang="en-US">1024cms.org 1024 CMS 0.7</title>
    <meta:item-metadata nvd-id="121218" status="DRAFT" modification-date="2010-12-14T19:38:32.197Z"/>
  </cpe-item>
  <cpe-item name="cpe:/a:1024cms:1024_cms:1.2.5">
    <title xml:lang="en-US">1024cms.org 1024 CMS 1.2.5</title>
    <meta:item-metadata nvd-id="121219" status="DRAFT" modification-date="2010-12-14T19:38:32.240Z"/>
  </cpe-item>
    <cpe-item name="cpe:/h:cisco:ips_4240">
    <title xml:lang="ja-JP">JAPAN IPS 4240 Sensor</title>
    <title xml:lang="en-US">EN Cisco IPS 4240 Sensor</title>
    <meta:item-metadata nvd-id="138255" status="DRAFT" modification-date="2011-01-12T14:36:11.990Z"/>
  </cpe-item>
</cpe-list>
'

doc = Nokogiri::XML(xml)
doc.at('title:nth-of-type(2)').to_xml # => "<title xml:lang=\"en-US\">EN Cisco IPS 4240 Sensor</title>"

CSS会产生一个非常清晰的选择器。或者,XPath可以这样做:

doc.at('//title[2]').to_xml # => "<title xml:lang=\"en-US\">EN Cisco IPS 4240 Sensor</title>"

在任何一种情况下,使用text来获取嵌入/子文本节点:

doc.at('title:nth-of-type(2)').text # => "EN Cisco IPS 4240 Sensor"
doc.at('//title[2]').text # => "EN Cisco IPS 4240 Sensor"

在任何一种情况下,您都可以使用CSS和/或XPath的功能将选择器扩展为更明确,以便在需要时查看参数及其值,但是,根据您的示例XML,您不需要&#39;吨。

这会找到所有匹配的<title xml:lang="en-US">标记&#39;文本:

doc.search('title[xml|lang="en-US"]').map(&:text) # => ["1024cms.org 1024 CMS 0.7", "1024cms.org 1024 CMS 1.2.5", "EN Cisco IPS 4240 Sensor"]

Nokogiri "Searching an HTML / XML Document" tutorial讨论了在&#34;命名空间&#34;中处理命名空间的问题。部分并且是重要的阅读。