Selenium Find By Xpath 返回错误的元素

Selenium Find By Xpath returning the wrong element

我正在尝试 select 显示在 HTML table 中的一系列频道中的一个频道。我正在使用以下 Selenium 方法 select link

WebElement channel = driver.findElement(By.xpath("//span[contains(text(),Sales)]")); channel.click();

但是它 select 是列表中的第一个频道(账户管理)。我希望它 select 正确的通道或抛出错误,而不是 select 错误的通道。以下是我要的频道的完整xpath:

/html/body/div[2]/div[2]/form/div/table/tbody[2]/tr/td/ul/li[2]/a/span

频道列表在HTML代码中定义如下:

<form action="nextpage.do" method="post" name="selectChannelForm">
<div class="de">
    <h2>Select channel</h2>
    <table id="selectChannelForm">
        <tbody id=""></tbody>
        <tbody id="">
            <tr rowtype="container">
            <td class="desecond" colspan="3">
                <ul>    
                <li>
                    <a id="selected_a" href="nextpage.do?selectedChannel=123">
                    <span>Account Management</span></a>
                </li>   
                <li>
                    <a id="selected_a" href="nextpage.do?selectedChannel=456">
                    <span>Sales</span></a>
                </li>
                <li>
                    <a id="selected_a" href="nextpage.do?selectedChannel=789">
                    <span>Complaints</span></a>
                </li>
                </ul>
            </td>
            </tr>
        </tbody>
    </table>
    <input type="hidden" value="selectChannelForm" name="formid">
</div>

您正在使用的 xpath 在 Sales 文本周围缺少引号 ""text() 函数接受一个字符串参数,字符串可以使用引号组成。按照以下方式更新您的 xpath -

driver.findElement(By.xpath("//span[contains(text(),'Sales')]")).click();

或者,如果您想将其分配给 WebElement,请在引号中加上 -

WebElement channel = driver.findElement(By.xpath("//span[contains(text(),'Sales')]"));
channel.click();

如果你想写嵌套双引号或嵌套单引号,那么使用转义字符 \ 来写它。方法如下 -

WebElement channel = driver.findElement(By.xpath("//span[contains(text(),\"Sales\")]"));
channel.click();

希望这对您有所帮助。

首先 - 你的错误!

您忘记了 "Sales" 两边的引号,只需稍微更改您的代码即可:

WebElement channel = driver.findElement(By.xpath("//span[contains(text(),'Sales')]"));
channel.click();

第二 - xpath 错误?

你是对的,这很奇怪,你没有收到错误消息,而是第一个元素是跨度。 这实际上可能是 xpath 中的错误。 contains 函数意识到您的第二个参数不是字符串,但它没有返回 false,而是 returns true.

它实际上命中了所有三个跨度项。结果你只得到第一个,因为你使用了 findElement 函数。

试试这个,你会发现怪癖:

System.out.println(driver.findElements(By.xpath("//span[contains(text(),Sales)]")).size());

结果将是:

3

第三 - 可能是 "as designed"

查看 w3c definition 您会发现以下行:

If the value of $arg2 is the zero-length string, then the function returns true.

然后在 xpath-site of microsoft 你会发现另一个有趣的谜题提示:

If an argument is not of type string, it is first converted to a string and then evaluated.

将所有这些信息放在一起,我猜 xpath 将您的 non-string/non-variable 第二个参数解释为空字符串,因此对于所有 span 元素 returns 为真,因为您正在搜索 //span .

更新

我们从@MichaelKay 的评论中了解到,我的 "guess" 非常接近:

In XPath and XQuery, a bare name like "hello" means child::hello, and if you're not using schema-awareness, then the system will just look for children called hello, and if there aren't any, it will return an empty node-set.

结论:OP 看到的行为是设计好的,尽管它看起来很不直观。

xpath需要修改为"//span[contains(text(),'Sales')]" .

正如我们在下面的方法定义中看到的那样,仅当第二个参数也是文本时,contains 方法才会 return 为真。

来源:https://en.wikipedia.org/wiki/XPath

包含(s1,s2) return如果 s1 包含 s2,则为真。 文本() 找到一个类型为 text

的节点