Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Iterations of elements in Nokogiri xpath

I tried to make iteration of some <li> elements

Iteration won’t work as expected:

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 this:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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

But I’m expected to see this:

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

Why xpath works so strange and how can I fix that?

>Solution :

You are missing a dot . at the beginning of your XPath expression.
Instead of

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

It should be

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

So the entire code piece will be:

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

This XPath expression //span[@class = 'price_comb']/text() is searching from the top of the document, not inside a specific node.
To make it search inside a node you should start the expression with a dot .: .//span[@class = 'price_comb']/text()

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading