在使用Selenium在网页中定位元素时,我使用了大量的XPath,并且最近使用node1 // node2转向使用node1 / descendant :: node2。这两种方法有什么区别?一个比另一个更有效吗?
用于演示的示例XML代码段:
<div id="books">
<table>
<tr><td class="title">Lord of the Rings</td><td class="author">JRR Tolkein</td></tr>
<tr><td class="title">The Hitch-Hikers Guide to the Galaxy</td><td class="author">Douglas Adams</td></tr>
</table>
</div>
所以它是:
id('books')//td[@class='title']
或:
id('books')/descendant::td[@class='title']
答案 0 :(得分:34)
请参阅http://www.w3.org/TR/xpath#path-abbrev
//只是descendant :: axis
的缩写修改强>
引用:
// para是/ descendant-or-self :: node()/ child :: para
的缩写
也就是说,它指的是所有para,它们是上下文节点的子节点或来自上下文节点的任何节点。据我所知,它转换为上下文节点的任何后代段。
答案 1 :(得分:11)
上下文组有所不同。 //para[1]
是简称
/descendant-or-self::node()/child::para[1]
,返回其父项的第一个子项的每个段。 /descendant::para[1]
仅返回整个子树中的第一个段落。
答案 2 :(得分:4)
在你的情况下
id('books')//td[@class='title']
和
id('books')/descendant::td[@class='title']
返回相同的结果。
但实际上,就像之前已经说过的那样,id('books')//td[@class='title']
表示id('books')/descendant-or-self::node()/td[@class='title']
在概念上与id('books')/descendant::td[@class='title']
不同。
请参阅以下注释:
注意:位置路径// para [1]与位置路径/ descendant :: para [1]的含义不同。后者选择第一个后代para元素;前者选择所有后代的para元素,这些元素是他们父母的第一个孩子。
答案 3 :(得分:2)
除了简洁之外,我不知道有什么不同。
答案 4 :(得分:1)
我意识到这个答案更多的是功能上的正确性,但如果它对任何人有帮助,我今天偶然发现了一个关键区别。
根据后代的某些属性(如属性)选择元素时。例如:
...
<foo id="ID1">
<bar>
<baz at2="c" />
</bar>
</foo>
<foo2 id="ID2">
<bar>
<baz at2="d" />
</bar>
</foo2>
...
要选择具有属性 id
的后代的所有元素的 at2=c
属性:
这个 xpath 将选择 foo 和 foo2:
//*[//*[@at2="c"]]/@id
虽然这个 xpath 只会选择 foo:
//*[descendant::*[@at2="c"]]/@id