【问题标题】:Exact match for string using XPath使用 XPath 精确匹配字符串
【发布时间】:2015-10-26 05:39:06
【问题描述】:

我编写了一个 xpath 来使用 selenium c# 从网页中抓取元素。

这里是 XPath

tbody/tr[@backcolor]/td/b/a[contains(text(),"match text")]

在我发现 match text 出现重复之前,这一切正常。因此,在网页上,我有两个带有 match text 的元素

一个是match text,另一个是match text 9000

现在,我只需点击match text。所以,我写了下面的XPath

table/tbody/tr[@bgcolor]/td/b/a[text()="   match text"]

请注意,匹配文本在网页上具有前导空格。上面的 Xpath 没有用。我已经用 Firefox 的 Fire Path 扩展检查了这一点。

谁能给我推荐一个 Xpath,它可以找到与 match text 完全匹配的东西。假设匹配文本可以包含任意数量的前导空格。

我也尝试过使用normalize-space(),但这也没有用。这是我试过的

text()[normalize-space(.)='match']

我发现了一些关于 SO 的问题,但没有帮助。

感谢您的帮助。

更新:

感谢您的回答,但没有一个对我有用。

我也提到了这两个字符串

  • 匹配文字
  • 匹配文本9000

在我的代码中,我将在 foreach 循环中迭代它们。所以,我不能保证我会得到 9000 作为第二个元素。

我已经尝试了使用 Firefox 的 FirePath 扩展程序提到的所有答案,但网页上没有选择任何内容。

如前所述,我在匹配文本之前有前导空格。

HTML:(匹配 xpath)

<html>
<body>
<table>
<tbody>
<tr><td><b><a class="s7intext" href="#">&nbsp;&nbsp; match text</a></b></td></tr>
<tr><td><b><a class="s7intext" href="#">&nbsp;&nbsp; match text random</a></b></td></tr>
</tbody>
</table>
</body>
</html>

这是我页面中的 HTML,其中包含 &amp;nbsp; 个字符。在match text 之前有两个&amp;nbsp; 字符和一个额外的空格。我正在抓取元素的站点是客户端站点。我不能说他修改他的 HTML 就可以了。

【问题讨论】:

  • “我也尝试过使用 normalize-space(),但也没有用。” (1) 你到底用 normalize-space() 尝试了什么? (2) 当你说事情没有奏效时,实际上发生了什么? XPath 表达式没有选择任何内容吗?有错误信息吗?
  • 在某个阶段您已经修改了问题,因此您的输入现在包括不间断的空格字符。这意味着该编辑之前的所有答案都将不再有效。以如此根本的方式改变问题会导致很大的混乱,最好开始一个新问题。 normalize-space() 去除“空白”;为此,不间断空格不被视为空白。要剥离它们,请使用 translate() 函数。

标签: c# selenium xpath exact-match


【解决方案1】:

对所有答案的评论:最好避免使用text(),因为这会使它对评论节点敏感。此外,一些(不正确的)XPath 实现无法连接相邻的文本节点,这些节点可能存在于以编程方式构建的 DOM 中。所以总是最好匹配元素的字符串值,而不是文本节点。无论如何,它更简单。这就是正确的解决方案:

tbody/tr[@backcolor]/td/b/a[normalize-space(.) = 'match text']

【讨论】:

  • 这没有用。感谢您提供有关 text() 的信息
  • 不起作用的原因是你改了问题。
【解决方案2】:

这两个选项之一应该可以工作,因为您使用 contains() 的 XPath 工作正常:

tbody/tr[@backcolor]/td/b/a[normalize-space(text()) = 'match text']

tbody/tr[@backcolor]/td/b/a[text()[normalize-space(.) = 'match text']]

输入 HTML 进行测试:

<div>
    <a>
       match text 900</a>
    <a>
       match text</a>
</div>

XPath 表达式测试:

//a[normalize-space(text()) = 'match text']

//a[text()[normalize-space(.) = 'match text']]

输出总是只有第二个&lt;a&gt; 元素(我测试了here,您可以使用任何其他选择的测试器)。如果这些都不起作用,请提供一个在 XPath 上失败的简化 HTML 标记。

更新:

根据更新中发布的 HTML sn-p,很清楚为什么 normalize-space() 不起作用。我会建议一种不同的方法。在 XPath 2.0 中,您可以使用 ends-with() 函数匹配 &lt;a&gt; 内部文本以 'match text' 结尾,如下所示:

//a[ends-with(.,'match text')]

如果 Selenium 不支持 XPath 2.0,您可以像这样在 XPath 1.0 中模拟 ends-with()

//a[substring(., string-length(.)-string-length('match text')+1) = 'match text']

【讨论】:

  • 对于 //a[text()[normalize-space(.) = 'match text']] ,当我使用 Selenium IDE (2.9.0) 进行测试时,这不起作用。我必须删除句点 - //a[text()[normalize-space() = 'match text']] - 然后它识别出正确的文本。
  • @NoSuchElephantException 感谢您在 Selenium 中进行测试(我没有安装它,也没有使用它的经验)。这将是有价值的信息。
  • 没问题。不过我有点错了!我做了更多的测试,看起来我可能打错了你原来的表达方式。两者现在都对我有效: //a[text()[normalize-space(.) = 'match text']] 和 //a[text()[normalize-space() = 'match text'] ] - 从理论上讲,我不确定哪个更好,但如果有人对一种表达有问题,他们可能会尝试另一种。
  • @har07 我想将其标记为答案,因为它正在 Xpath 测试中工作。但这在我的浏览器中不起作用
【解决方案3】:

您的第一次尝试已经接近。

如果 9000 匹配是唯一不想要的匹配 尝试使用 'not' 排除 9000 匹配:

tbody/tr[@backcolor]/td/b/a[contains(text(), 'match text') and not (contains(text(), '9000'))]

【讨论】:

    猜你喜欢
    • 2021-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多