如何根据外部标记匹配获取内容?

时间:2013-05-26 02:53:38

标签: ruby arrays nokogiri

我正在尝试根据链接和名称所在组之外的标记组织链接和名称列表。它的设置如下:

<h4>Volkswagen</h4>
<ul>
   <li><a href="http://beetle.cars.com">beetle</a></li>
</ul>

<h4>Chevy</h4>
<ul>
  <li><a href="http://volt.cars.com">Volt / Electric</a></li>
</ul>

我需要的是以下列格式的结果,最终将名称作为链接,但如果我能正确组织这些项目,我可以稍后再做。

每个汽车品牌可能有多种不同数量的模型。我需要按汽车品牌组织它们:

Volkswagen
   Beetle Link  Beetle
   Jetta Link   Jetta

Chevy
   Volt Link  Volt / Electric
   S10 Link  S10

我可以毫无问题地获得品牌列表。我只是很难将一批模型与每个品牌相关联,因为<h4>标签没有嵌套,所以我不知道如何将它们与以下<ul>汽车列表相关联。< / p>

1 个答案:

答案 0 :(得分:0)

我更喜欢直接潜入每辆车,然后退出以提取汽车的品牌:

cars = Hash.new { |h, k| h[k] = [] }

doc.xpath('//ul/li/a').each do |car|
  brand = car.at('../../preceding-sibling::h4[1]').text
  cars[brand] << {link: car['href'], name: car.text}
end

请注意,使用指定默认值为数组的块初始化哈希。这允许附加哈希值(通过<<),如图所示。 XPath ../../preceding-sibling::h4[1]说:返回到ul级别并回顾前面的第一个h4。这是该车的相应品牌。

输出:

{"Volkswagen"=>[
                {:link=>"http://beetle.cars.com", :name=>"beetle"}
                # others here
               ],
 "Chevy"=>[
           {:link=>"http://volt.cars.com", :name=>"Volt / Electric"}
           # others here
          ]
}

我觉得这个技术很简单,只需一个循环。不是每个人都喜欢这种风格。