如何分别从两个相同的节点获取内容?

How to take content from two same nodes separately?

我有 HTML 包含产品名称和价格列表的文件

<ul>
  <li>
    <label>
      <span class="name">Name 1</span>
      <span class="price">3.99</span>
    </label>
  </li>
  <li>
    <label>
      <span class="name">Name 2</span>
      <span class="price">5.49</span>
    </label>
  </li>
...
</ul>

并且需要分别从每个 <label> 中获取名称和价格。 我正在使用 Nokogiri 解析 HTML 文件并尝试

file.xpath('//ul/li/label').each do |item|
  puts item.content
end

但是,您可能已经猜到了,它 returns 名称和价格。

名称和价格 span 元素是 label 元素的子元素,因此您可以在每个 label[=16= 的范围内使用 xpath 获取它们]

file.xpath('//ul/li/label').each do |item|
  name = item.at_xpath("span[@class='name']").text()
  price = item.at_xpath("span[@class='price']").text()
  puts "#{name} - #{price}"
end

或使用css选择器

file.xpath('//ul/li/label').each do |item|
  name = item.at_css('.name').text()
  price = item.at_css('.price').text()
  puts "#{name} - #{price}"
end

通常我会使用这样的东西:

require 'nokogiri'

doc = Nokogiri::HTML(<<EOT)
<ul>
  <li>
    <label>
      <span class="name">Name 1</span>
      <span class="price">3.99</span>
    </label>
  </li>
  <li>
    <label>
      <span class="name">Name 2</span>
      <span class="price">5.49</span>
    </label>
  </li>
</ul>
EOT

data = doc.css('label').map { |label| [label.at('.name').text, label.at('.price').text] }.to_h 
# => {"Name 1"=>"3.99", "Name 2"=>"5.49"}

只要 .name 文本是唯一的(从示例 HTML 看来应该如此),生成的散列将有效且易于使用。

IF 如果您需要它们,那么 Ruby 将 return key/value 按它们最初插入的顺序排列,如果您迭代它们,这不是我推荐依赖的东西,因为在其他语言中你不能依赖它,但你的里程可能会有所不同。否则,无论有多少条目,为给定键检索值的查找都非常快,因为它是一个散列。而且,可以传递散列以进行大量有用的修改。