В чем разница между `@attr! =" Value "` и `not (@ attr =" value ")` в XPath - PullRequest
3 голосов
/ 15 мая 2019

Существует такой HTML-код.

<div class="paginate_box">
  <span class="disabled prev_page">Back</span>
  <span class="current">1</span>
  <a rel="next" href="page2">2</a>
  <a rel="next" href="page3">3</a>
  <a class="next_page" rel="next" href="page2">Next</a>
</div>

Чтобы получить наибольшее количество страниц, которые я написал.

doc = Nokogiri::HTML(html)
doc.xpath('//div[@class="paginate_box"]/a[not(@class="next_page")]').last.text
#=> "3"

Сначала я написал a[@class!="next_page"] вместо a[not(@class="next_page")], но он не соответствует тегу.Почему это не совпадает?Что я делаю не так?

1 Ответ

2 голосов
/ 15 мая 2019

Итак, проблема в том, что вы пытаетесь использовать != для атрибута (@class), который присутствует только на последнем узле.Это означает, что @class нельзя сравнивать на других узлах, потому что по сути это ничего не говорит! = 'Next_page'.

Поскольку ничто не сравнимо ни с чем, операторы (включая != и =) всегда будут возвращать false.

В вашей функции not вы спрашиваете, если ничего = 'next_page', которая всегда false (как объяснено выше), и, таким образом, not делает его true и элемент выбран.

Вы можете доказать это, добавив класс к одному из других тегов привязки, а затем использовать версию !=.

Примечание: вы можете упростить код, просто используя xpath

doc.xpath('//div[@class="paginate_box"]/a[not(@class="next_page")][last()]').text 
#=> "3"
# Or  
doc.xpath('//div[@class="paginate_box"]/a[not(@class="next_page")][last()]/text()').to_s
#=> "3"

Также, если якорь next_page всегда присутствует и всегда последняя, ​​а наибольшему номеру страницы всегда предшествует, тогда вы можете избежатьобщее условие:

doc.xpath('//div[@class="paginate_box"]/a[position()=last()-1]').text
#=> "3"

Здесь мы говорим: найдите якорь в позиции прямо перед последним в этом div.

Альтернатива:

doc.xpath('//div[@class="paginate_box"]/a[last()]/preceding-sibling::a[1]').text
#=> "3"

Это найдет последний якорь, затем все предшествующие ему якорные братья и сестры в порядке снизу вверх, и мы выбираем первый в этом списке.

...