使用Nokogiri根据子属性的值来拉取父属性的值

时间:2014-07-25 13:10:44

标签: ruby xml xpath nokogiri

我有一些我需要从中提取值的xml。非常简化的版本如下:

...
<event id="380783">
  ...
  <competitor id="1929" name="x">
    <homeaway>home</homeaway>
  </competitor>
  ...
</event>
...

有许多活动,每个活动都有一个家庭活动。团队和一个离开&#39;团队 - 我需要获得家庭和外出的竞争对手ID,但我需要知道哪个是哪个。

就我自己而言,我可以像这样获得ID:

doc.xpath("//event[@id=#{uid}]//competitor").attr('id').value

我还可以找出一个给定的节点是否是“家”。或者&#39;离开&#39;

2.1.1 :107 > first_match.xpath('//event[@id=#{uid}]//competitor//homeaway').children[0].text
 => "home" 
2.1.1 :108 > first_match.xpath('//event[@id=#{uid}]//competitor//homeaway').children[1].text
 => "away" 

但是我希望找到无论是回家还是离家的id。类似的东西:

away = xpath('//event[@id=#{uid}]//competitor//homeaway).children.text == away
away.parent.attr('id')

我怎么能这样做?

2 个答案:

答案 0 :(得分:1)

如何做到这一点(使用ancestor轴获取id competitor}:

home_id = doc.at_xpath(
  "//event[@id=#{uid}]//competitor//homeaway[text()='home']" +
  "/ancestor::competitor/@id").value

away_id = doc.at_xpath(
  "//event[@id=#{uid}]//competitor//homeaway[text()='away']" +
  "/ancestor::competitor/@id").value

答案 1 :(得分:1)

不需要复杂的xpath:

xml2.xml:

<?xml version="1.0" encoding="UTF-8"?>
<events>

<event id="380783">
  <competitor id="1929" name="x">
    <homeaway>home</homeaway>
  </competitor>

  <competitor id="1930" name="x">
    <homeaway>away</homeaway>
  </competitor>
</event>

<event id="380784">
  <competitor id="1931" name="x">
    <homeaway>away</homeaway>
  </competitor>

  <competitor id="1932" name="x">
    <homeaway>home</homeaway>
  </competitor>
</event>

</events>

...

require 'nokogiri'

f = File.open("xml2.xml")
doc = Nokogiri::XML(f)
f.close

uid = 380784
event = doc.at_xpath("//event[@id=#{uid}]")
competitor_ids = {}

event.xpath('.//competitor').each do |competitor|
  id = competitor.attr('id').to_i
  homeaway = competitor.at_xpath('.//homeaway').text
  competitor_ids[id] = homeaway 
end

p competitor_ids

--output:--
{1931=>"away", 1932=>"home"}

如果需要,您可以将整个xml文件组织成一个哈希,以便以您想要的方式访问数据变得简单:

require 'nokogiri'

f = File.open("xml2.xml")
doc = Nokogiri::XML(f)
f.close


events = Hash.new { |hash, key| hash[key] = {}}

doc.xpath("//event").each do |event|
  event_id = event.attr('id').to_i

  event.xpath('.//competitor').each do |competitor|
    competitor_id = competitor.attr('id').to_i
    homeaway = competitor.at_xpath('.//homeaway').text
    events[event_id][homeaway] = competitor_id
  end
end

p events

uid = 380784
puts events[uid]['home']

--output:--
{380783=>{"home"=>1929, "away"=>1930}, 380784=>{"away"=>1931, "home"=>1932}}
1932