125

我使用XPather Browser在 HTML 页面上检查我的 XPATH 表达式。

我的最终目标是在 Selenium 中使用这些表达式来测试我的用户界面。

我得到了一个 HTML 文件,其内容类似于:

<tr>
  <td>abc</td>
  <td> </td>
</tr>

我想选择一个文本包含字符串“ &nbsp;”的节点。

使用像“abc”这样的普通字符串没有问题。我使用类似于//td[text()="abc"].

当我尝试使用 XPATH时,//td[text()="&nbsp;"]它什么也不返回。对带有“”的文本有特殊规定&吗?

4

7 回答 7

93

似乎 Selenium 背后的OpenQA已经解决了这个问题。他们定义了一些变量来明确匹配空格。就我而言,我需要使用类似于//td[text()="${nbsp}"].

我在此处复制了 OpenQA 关于此问题的文本(在此处找到):

HTML 自动规范化元素中的空白,忽略前导/尾随空格并将额外的空格、制表符和换行符转换为单个空格。当 Selenium 从页面中读取文本时,它会尝试复制此行为,因此您可以忽略 HTML 中的所有制表符和换行符,并根据呈现时文本在浏览器中的外观进行断言。我们通过用一个空格替换所有不可见的空格(包括不间断空格“ &nbsp;”)来做到这一点。应保留所有可见的换行符(<br><p>和格式化的换行符)。<pre>

我们对 HTML Selenese 测试用例表的文本使用相同的规范化逻辑。这有许多优点。首先,您不需要查看页面的 HTML 源代码来确定您的断言应该是什么;" &nbsp;" 符号对最终用户是不可见的,因此在编写 Selenese 测试时不必担心它们。(您不需要&nbsp;在测试用例中放置“”标记来断言包含“ &nbsp;”的字段上的文本。)您还可以在 Selenese <td>标记中放置额外的换行符和空格;由于我们在测试用例上使用与文本相同的规范化逻辑,因此我们可以确保断言和提取的文本将完全匹配。

当您真的想要/需要在测试用例中插入额外的空格时,这会在极少数情况下产生一些问题。例如,您可能需要在如下字段中键入文本:“ foo ”。但是,如果您只是<td>foo </td>在 Selenese 测试用例中编写代码,我们将仅用一个空格替换您的多余空格。

这个问题有一个简单的解决方法。我们在 Selenese 中定义了一个变量 ${space},它的值是一个空格。您可以使用${space}插入不会自动修剪的空格,如下所示: <td>foo${space}${space}${space}</td>. 我们还包括了一个变量 ${nbsp},您可以使用它来插入一个不间断的空格。

请注意,XPath不会像我们那样规范化空白。如果您需要编写一个 XPath, //div[text()="hello world"]但链接的 HTML 确实是“ ”,则需要在 Selenese 测试用例 hello&nbsp;world中插入一个真正的“ ”以使其匹配,如下所示: .&nbsp;//div[text()="hello${nbsp}world"]

于 2008-10-29T18:34:39.450 回答
29

我发现当我通过在 Windows 上的两个引号之间键入 Alt+0160 输入硬编码的不间断空格 (U+00A0) 时,我可以进行匹配...

//table[@id='TableID']//td[text()=' ']

使用特殊字符为我工作。

据我了解,XPath 1.0 标准不处理转义 Unicode 字符。XPath 2.0 中似乎有这样的功能,但看起来 Firefox 不支持它(或者我误解了一些东西)。所以你必须与本地代码页有关。丑陋,我知道。

实际上,看起来标准依赖于使用 XPath 的编程语言来提供正确的 Unicode 转义序列......所以,不知何故,我做对了。

于 2008-10-29T16:09:14.983 回答
5

尝试使用小数实体&#160;而不是命名实体。如果这不起作用,您应该能够简单地使用unicode 字符作为不间断空格而不是&nbsp;实体。

(注意:我没有在 XPather 中尝试过,但我确实在 Oxygen 中尝试过。)

于 2008-10-29T15:57:33.837 回答
5

根据您提供的 HTML:

<tr>
  <td>abc</td>
  <td>&nbsp;</td>
</tr>

要使用字符串定位节点,&nbsp;您可以使用以下任一基于的解决方案:

  • 使用text()

    "//td[text()='\u00A0']"
    
  • 使用contains()

    "//td[contains(., '\u00A0')]"
    

但是,理想情况下,您可能希望避免使用NO-BREAK SPACE字符并使用以下任一定位器策略

  • 使用父<tr>节点和following-sibling

    "//tr//following-sibling::td[2]"
    
  • 使用starts-with()

    "//tr//td[last()]"
    
  • 使用前面的<td>节点和followingnode and后面的兄弟节点:

    "//td[text()='abc']//following::td[1]"
    

参考

您可以在以下位置找到相关的详细讨论:


tl; 博士

Unicode 字符 'NO-BREAK SPACE' (U+00A0)

于 2020-01-11T22:05:54.820 回答
1

请记住,在评估 XPath 表达式时,符合标准的 XML 处理器将用目标编码中的相应字符替换除 XML 的五个标准引用( &amp;&gt;&lt;&apos;、 )之外的任何实体引用。&quot;鉴于这种行为,如果您想使用 XML 工具,PhiLho 和 jsulak 的建议是您的最佳选择。在输入&#160;XPath 表达式时,应先将其转换为相应的字节序列,然后再应用 XPath 表达式。

于 2008-10-29T19:27:59.310 回答
0

搜索&nbsp;或仅搜索nbsp- 您尝试过吗?

于 2008-10-29T15:05:47.453 回答
0

我无法使用 Xpather 获得匹配,但以下内容适用于 Microsoft 的 XML 记事本中的纯 XML 和 XSL 文件:

<xsl:value-of select="count(//td[text()='&nbsp;'])" />

返回的值为 1,这是我的测试用例中的正确值。

但是,我确实必须使用以下命令在我的 XML 和 XSL 中将nbsp声明为一个实体:

<!DOCTYPE xsl:stylesheet [ <!ENTITY nbsp "&#160;"> ]>

我不确定这是否对您有帮助,但我实际上能够使用 XPath 表达式找到nbsp 。

编辑:我的代码示例实际上包含字符' ' 但是 JavaScript 语法高亮将其转换为空格字符。不要被误导!

于 2008-10-29T17:12:35.933 回答