我有两个几乎相同的表,唯一的区别是第一个中的输入标记:
表#1
<table>
<tbody>
<tr>
<td>
<div>
<input type="text" name="" value=""/>
</div>
</td>
</tr>
</tbody>
</table>
表#2
<table>
<tbody>
<tr>
<td>
<div></div>
</td>
</tr>
</tbody>
</table>
</body>
当我使用这个XPath //table//tbody//tr[position()=1 and contains(.,input)]
时,它返回两个表的第一行,而不仅仅是我期望的第一个表第一行。
但是,此XPath //table//tbody//tr[position()=1]//input
仅返回第一个input
。
那么,我做错了什么?为什么同一个input
与两个表相关联?我是否在某种程度上滥用了.
?
答案 0 :(得分:7)
由于功能名称 1 中的不幸选择,许多人误以为XPath中contains()
函数的用途:
contains()
不 检查 元素
遏制。contains()
检查 子串 包含。因此,tr[contains(.,input)]
没有按照您的想法行事。它实际上选择tr
个元素,其string-value包含的子字符串等于第一个直接子input
元素的字符串值;有关详细信息,请参阅this answer。 (有趣的是,这样的谓词简化为true,因为字符串值定义的分层特性意味着父元素和子元素的字符串值之间的子字符串包含。)无论如何,这显然不是你的意图。
要检查后代元素包含,请改用.//input
。如果你想要选择tr
元素,那么这可以作为你的第一个XPath尝试的tr
的谓词放置,
//table//tbody//tr[position()=1 and .//input]
或table
(as shown by @Andersson),如果您希望选择包含table
后代元素的input
个元素:
//table[.//input]
为什么XPath contains()
应该被命名为string-contains()
1 在XML的上下文中,它强烈地基于层次结构的概念,很自然地假设 contains 指的是层次包含。在原始XPath规范中出现 contains 这个词的24次中,19次意味着分层节点包含;只有5次意味着子串遏制。毫无疑问,contains()
存在混淆。 XPath子串contains()
函数应该已命名为 string-contains() 。
答案 1 :(得分:3)
你应该试试
//table[.//input]
获取具有table
后代
input
节点