XPath 中的“@attr!="value"”和“not(@attr="value")”有什么区别

What is the difference between `@attr!="value"` and `not(@attr="value")` in XPath

有一个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")],但是和标签不符。为什么不匹配?我做错了什么?

所以这里的问题是您正试图在仅存在于最后一个节点上的属性 (@class) 上使用 !=。这意味着 @class 无法在其他节点上进行比较,因为它实际上什么也没说!= 'next_page'。

因为没有什么是不可比的,运算符(包括!==)总是return假。

在你的 not 函数中你问的是 nothing = 'next_page' 它总是 false (如上所述)因此 not 使它成为 true 并选择元素。

您可以通过向其他锚标记之一添加 class 然后使用 != 版本来证明这一点。

旁注,您可以简化代码以仅使用 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"

这将找到最后一个锚点,然后按自下而上的顺序找到它前面的所有锚点兄弟姐妹,我们将选择该列表中的第一个。