XPath表达式//*[contains(.,'sometext')]与//*[contains(text(),'sometext')]的差异探究
XPath表达式
//*[contains(.,'sometext')]与//*[contains(text(),'selenium')]的差异解析 核心逻辑区别
1. contains(text(),'sometext')的匹配规则
text()提取的是当前元素直接子级的所有独立文本节点——注意是「直接子级」,嵌套在子元素里的文本不算。contains(text(),'sometext')只会在这些独立文本节点中,找某一个单独节点完整包含目标字符串的情况,只要没有单个节点符合,就不会匹配。
举个实际场景:
<p>自动化测试工具 <b>selenium</b> 入门</p>
这个<p>的text()返回两个文本节点:["自动化测试工具 ", " 入门"],<b>里的selenium属于子元素的文本,不在<p>的直接文本节点集合里,所以//p[contains(text(),'selenium')]不会匹配这个<p>。
2. contains(.,'sometext')的匹配规则
.代表当前元素的完整字符串值:它会把当前元素及其所有后代(不管嵌套多少层)的所有文本内容,全部拼接成一个无分隔的字符串。contains(.,'sometext')只检查这个拼接后的字符串里是否包含目标内容,不管内容来自单个节点还是多个节点的拼接。
还是上面的例子,<p>的.字符串值是"自动化测试工具 selenium 入门",包含selenium,所以//p[contains(.,'selenium')]会匹配这个<p>。
测试页面匹配数量差异的原因
你测试的页面中,contains(.,'selenium')匹配数远多于contains(text(),'selenium'),核心是两类场景的大量存在:
- 嵌套结构的文本继承:很多父元素本身没有直接包含
selenium的文本,但子元素、孙元素里有,父元素的.会把后代文本全部拼接进来,因此被匹配;而父元素的text()只返回自身直接子级的文本,不含后代内容,所以不会被contains(text(),'selenium')命中。 - 文本拆分在多个节点:部分元素的
selenium被其他标签拆成了多个片段,比如<span>sele</span><span>nium</span>,单个文本节点都不包含完整的selenium,所以contains(text(),'selenium')不匹配;但拼接后的字符串是完整的selenium,因此被contains(.,'selenium')命中。
内容的提问来源于stack exchange,提问作者Prophet
相关产品推荐
相关产品推荐

