Nokogiri xpath 中元素的迭代

Iterations of elements in Nokogiri xpath

我尝试对一些 <li> 元素进行迭代

迭代无法按预期工作:

require 'nokogiri'

doc = Nokogiri::HTML(<<-END_OF_HTML)
  <ul class="attribute_radio_list">
    <li>
      <input type="radio" name="group_4" value="709" id="comb_709_group_4" checked="checked">
      <label for="comb_709_group_4" class="label_comb_price label_comb_price_punda comb_709_group_4 checked">
        <span class="radio_label">1-10 kg</span>
        <span class="price_comb">14.85 €</span>
      </label>
      <span class="pundaline-variations-tooltip">1-10 kg</span>
    </li>
    <li class=" comb_710_group_4_li" id="comb_710_group_4_li">
      <input type=" radio" name="group_4" value="710" id="comb_710_group_4">
      <label for="comb_710_group_4">
        <span class="radio_label">10-20 kg</span>
        <span class="price_comb">17.82 €</span>
      </label>
      <span class="pundaline-variations-tooltip">10-20 kg</span>
    </li>
    <li id="comb_711_group_4_li">
      <input type=" radio" name="group_4" value="711" id="comb_711_group_4">
      <label for="comb_711_group_4">
        <span class="radio_label">20-40 kg</span>
        <span class="price_comb">19.80 €</span>
      </label>
      <span class="pundaline-variations-tooltip">20-40 kg</span></li>
  </ul>
END_OF_HTML

lis = doc.xpath("//li")

lis.each do |li|
  p li.xpath("//span[@class = 'price_comb']/text()").to_s
end

returns 这个:

"14.85 €17.82 €19.80 €"
"14.85 €17.82 €19.80 €"
"14.85 €17.82 €19.80 €"

但我应该看到这个:

"14.85 €"
"17.82 €"
"19.80 €"

为什么 xpath 工作起来很奇怪,我该如何解决?

您的 XPath 表达式开头缺少一个点 .
而不是

"//span[@class = 'price_comb']/text()"

应该是

".//span[@class = 'price_comb']/text()"

所以整个代码片段将是:

lis.each do |li|
  p li.xpath(".//span[@class = 'price_comb']/text()").to_s
end

此 XPath 表达式 //span[@class = 'price_comb']/text() 是从文档的顶部开始搜索,而不是在特定节点内。
要使其在节点内搜索,您应该以点 . 开头表达式:.//span[@class = 'price_comb']/text()
更新
正如 engineersmnky 提到的,可能有用:

  • 圆点.是相对路径,表示只会在节点内搜索。
  • 双斜杠“//”表示该节点内的任何位置;
  • 其中单斜杠“/”只是直系后代。
  • Xpath Cheatsheet 可能会帮助您掌握基础知识