2011-01-29 140 views
1

在使用XPath读取XML方面已经写了很多有关Nokogiri的文章。但是,使用包含XPath引用的XML的Nokogiri有什么用处。如何让Nokogiri在解析XML时解析XPath引用?

在该示例中,XML包含的XPath参考:

<elements> 
<element> 
    <location> 
    <longitude>... 
    <latitude>... 
    </location> 
</element> 
<element> 
    <location reference="../../element/location"/> 
</element> 
</elements> 

由于两个位置元素是相等的,只有第一元件进行详细说明。第二个只是引用第一个。

使用Nokogiri,xml.xpath('// location')按预期返回两个节点实例。第一个节点包含所有的子节点。第二个仅作为第二个节点实例的属性的引用。好吧,假设我想请求所有的经度值,我会xml.xpath('// location/longitude')。这只返回一个节点实例。然而,由于实际上有型,我有望获得两个节点的情况下,期望引入nokogiri解决的XPath引用的“经度”两个元素...

我怎样引入nokogiri实现这一目标?

+1

我只在你的例子中看到一个经度元素。你能更详细地了解输入和你想要提取什么? – 2011-01-29 14:42:02

+0

您在多个网站上提问,包括[Nokogiri Talk](http://groups.google.com/group/nokogiri-talk)。开发者监视这个列表,但很少访问这里,所以请用他们提供的答案更新你的问题。 – 2011-01-29 21:35:19

回答

1

你可以收集具有实际值(非参考节点),然后分别收集所有的引用位置的节点,如下面的代码片段演示:

require 'nokogiri' 

xml = <<End 
<elements> 
<element> 
    <location> 
    <longitude>45</longitude> 
    <latitude>-70</latitude> 
    </location> 
</element> 
<element> 
    <location reference="../../element/location"/> 
</element> 
</element> 
End 

doc = Nokogiri::XML(xml) 

#Collect all the explicit longitudes 
longitudes = doc.search('//location[not(@reference)]/longitude').map(&:text) 

#Follow references to longitudes 
doc.search('//location[@reference]').each do |location| 
    reference = location.attribute('reference') 
    longitudes << location.xpath("#{reference}/longitude").text 
end 

puts longitudes #=> ["45", "45"] 

你可以以这个技术提取的任何信息你想。

0

您没有提供任何线索的第二location元素如何引用第一。

即使这种机制被称为,我们能够将其指定在XPath表达式来选择所引用的location元件,所述选择的两个longitude节点将是相同的

当XPath表达式被评估它总是返回一个设定的节点的 - 也就是说,如果同一个节点被选择不止一次它是在选择结果表示只有一次 - 一组没有按” t包含重复的项目。

这就是为什么,在longitude元素将只显示在选择一次,即使它被选择两次。

这里是一个例子;

XPath表达式

/一个/ * | // c/..

只选择一个元素b - 不是两个完全相同的元素b