XPath谓词查询/bookstore/book[last()-1]的选取规则是什么
XPath表达式
/bookstore/book[last()-1]选取规则说明 W3Schools给出的“选取bookstore子元素中倒数第二个book”的结论,只在无额外筛选、以根节点为起点的绝对路径默认场景下成立,并非所有场景都符合这个预期,核心逻辑要从XPath谓词的运行规则拆解:
- 谓词中
last()函数的返回值,是当前谓词所属步骤匹配到的上下文节点集的总节点数,不是固定取父节点下最后一个节点的序号;[n]谓词筛选的是当前上下文节点集中,position()等于n的节点。 - 当你使用无额外筛选的绝对路径
/bookstore/book时,上下文节点集是所有作为bookstore直接子元素的<book>节点,节点默认按XML文档中的出现顺序(文档顺序)排列,此时last()等于该集合的总长度,last()-1对应的位置正好是集合里的倒数第二个节点,和教程描述一致。 - 只要当前步骤的上下文节点集发生变化,结果就会偏离“bookstore下倒数第二个book子元素”的预期:
- 如果路径加了属性、内容筛选,比如
/bookstore/book[@price>50][last()-1],上下文节点集是所有价格大于50的book子元素,此时选到的是「价格大于50的book里的倒数第二个」,不是全量book里的倒数第二个。 - 如果路径用了反向轴(比如
preceding-sibling::book),节点集默认按反向文档顺序排列,position()计数方向反转,last()-1对应的位置也会完全变化。
- 如果路径加了属性、内容筛选,比如
- 还要注意:
/bookstore/book本身就只会匹配类型为<book>的直接子元素,会自动忽略bookstore下其他类型的子节点(比如杂志、食谱类的其他标签),所以哪怕其他类型节点插在book节点之间,也不会被计入上下文节点集,选出来的结果和“bookstore所有子元素里排倒数第二的book”也不是一个概念。
举个直观的验证样例:
<bookstore> <book id="1">前端基础</book> <magazine id="2">程序员月刊</magazine> <book id="3">XPath实战</book> <book id="4">算法导论</book> <notebook id="5">学习手账</notebook> </bookstore>
上述文档中执行/bookstore/book[last()-1],匹配到的上下文节点集是id=1、3、4的三个book节点,last()返回3,last()-1对应位置2,最终选中id=3的book节点——这个节点在bookstore所有直接子元素里排第3位,显然不是全量子元素里的倒数第二个。
内容的提问来源于stack exchange,提问作者John Jacob
相关产品推荐
相关产品推荐

