关于preceding轴与//、/结合的遍历疑问:首个XPath是否定位指定div
XPath中preceding轴与路径符号的疑问解答
相关HTML结构
<div id="moe-osm-pusher" style="display: block !important; height: 0px;"> <div><p>A44</p></div> </div> <div id="x"> <p>A</p> <div> <div> <p>A11</p> </div> <div> <p>A12</p> <div> <p>A13</p> </div> <div> <p>A23</p> <div><p>A00</p></div> </div> </div> <div> <p>A22</p> </div> </div> </div>
涉及的两条XPath
//div[p[contains(text(),'A23')]]//preceding::div//div[p[contains(text(),'A23')]]/preceding::div
疑问解答
第一条XPath不会定位到<div><p>A00</p></div>,原因如下:
- 先明确
preceding轴的核心规则:它只会选取文档顺序中出现在当前节点之前的节点,且排除当前节点的父节点、自身、后代节点。 <div><p>A00</p></div>是目标节点//div[p[contains(text(),'A23')]]的直接子节点,在文档顺序中出现在目标节点内部的<p>A23</p>之后,属于目标节点的后代,完全不在preceding轴的选取范围内。- 再看两条XPath的差异:
- 第二条用
/preceding::div:直接选取目标节点的preceding轴下的所有div,也就是文档中在目标节点之前的符合条件的节点。 - 第一条用
//preceding::div:这里的//是/descendant-or-self::node()/的缩写,等价于先选取目标节点及其所有后代节点,再对每个节点取preceding轴的div。但<div><p>A00</p></div>作为目标节点的后代,它的preceding轴也只能选取文档中在它之前的节点,并不会包含它自己,因此最终结果和第二条XPath一致,都不会出现这个div。
- 第二条用
你看到的两条XPath共同输出的四个div是符合preceding轴规则的,它们都是文档顺序中在目标节点之前的div节点。
内容的提问来源于stack exchange,提问作者Saumyojit Das
相关产品推荐
相关产品推荐

