为何XPath返回元素超出预期?//div["someClass"]/p[1]匹配异常解析
首先,你的XPath表达式存在语法逻辑错误:要匹配class为someClass的div节点,正确的谓语写法是div[@class='someClass'](精确匹配class属性),或者div[contains(@class, 'someClass')](适合div有多个class的模糊匹配场景)。
1. 错误表达式//div["someClass"]/p[1]的问题
你写的["someClass"]是一个字符串字面量,在XPath的布尔判断规则中,非空字符串会被视为true,所以这个谓语相当于没有任何过滤条件,等价于//div/p[1]——也就是匹配所有div节点下的第一个子p元素。
你提到这个表达式返回了外层的<p>Foo</p>,大概率是对结果的误解或表达式存在笔误(比如误写为//div["someClass"] | //p[1])。正常情况下,//div/p[1]只会匹配示例中div下的<p>Bar</p>,不会命中外层的p节点。如果确实出现该异常,可能是DOMXPath对错误表达式的解析存在特殊 fallback,但核心问题还是表达式写法错误。
2. 为什么//*/div["someClass"]/p[1]能返回预期结果
//*表示匹配任意类型的节点,//*/div则表示匹配作为任意节点子节点的所有div。在你的示例HTML中,只有一个div节点(根节点的子节点),//*/div可以命中它。加上无效的["someClass"]谓语后,依然等价于//*/div/p[1],刚好命中你要的<p>Bar</p>。
这只是巧合,并非正确写法——如果页面中有其他div节点,这个表达式会错误匹配那些div下的p元素。
正确的表达式写法
想要精准匹配class为someClass的div下的第一个子p元素,应该用:
//div[@class='someClass']/p[1]
如果div可能包含多个class(比如class="someClass otherClass"),则用模糊匹配:
//div[contains(@class, 'someClass')]/p[1]
内容的提问来源于stack exchange,提问作者online Thomas

