在XPath中选择基本元素的多个子元素时,我无法清楚地理解使用//element
和/descendant::element
之间的区别。
鉴于此HTML代码段
<html>
<body>
<div class="popupContent">
<table>
<tr class="aclass"><td> Hello </td> <td> <input type="text" value="FIRST" /> </td></tr>
<tr class="aclass"><td> Goodbye </td> <td> <input type="text" value="SECOND" /> </td></tr>
</table>
</div>
</body>
</html>
我需要根据其在表格中的位置来选择每个input
。
//div[@class='popupContent']//input[1]
这会选择第一个输入
//div[@class='popupContent']//input[2]
这会产生错误
//div[@class='popupContent']/descendant::input[1]
这再次选择第一个输入
//div[@class='popupContent']/descendant::input[2]
这会选择第二个输入
使用/descendant::input
做我需要的:抓住所有输入并让我按位置选择
//
有何不同?为什么它只返回第一个元素而不是之后的元素?
我知道this other question,但答案基本上是说他们是别名并指向文档,我无法理解,缺乏具体的例子。
答案 0 :(得分:10)
根据XPath 1.0, §2.5 Abbreviated Syntax:
的缩写
//
是/descendant-or-self::node()/
所以div[@class='popupContent']//input[1]
(与div[@class='popupContent']/descendant-or-self::node()/child::input[1]
相同)将:
div
s的所有后代(孩子,孩子的孩子等),<input>
个孩子[1]
谓词) div[@class='popupContent']//input[2]
非常相似,但最后一件事是选择第二个孩子。
<input>
s中没有一个是他们父母的第二个孩子。
div[@class='popupContent']/descendant::input[2]
将:
div
的所有后代<input>
元素,并从中构建节点集 您可以在§2.4 Predicates中阅读谓词和轴。相关部分:
(...)祖先,祖先或自我,前面和前面的兄弟轴是反向轴; 所有其他轴都是前轴。
[因此descendant
是前轴。]
节点集的成员相对于轴的接近位置被定义为按文档顺序排序的节点集中节点的位置(如果轴)是前轴(...)。第一个位置是1.
谓词过滤相对于轴的节点集以生成新的节点集。对于要过滤的节点集中的每个节点,使用该节点作为上下文节点评估
PredicateExpr
,其中节点集中的节点数作为上下文大小,具有接近度节点集中节点相对于轴的位置作为上下文位置;
答案 1 :(得分:1)
//X
和/descendant::X
之间的唯一区别是X包含位置谓词,例如//x[1]
vs /descendant::x[1]
。在这种情况下,//x[1]
会选择作为其父元素的第一个x
子元素的每个x
元素,而/descendant::x[1]
会选择整个第一个后代x。您可以通过记住//x[1]
是/descendant-or-self::node()/child::x[1]