Selenium Find By Xpath返回错误的元素

时间:2015-10-04 11:11:50

标签: java html selenium xpath xquery

我正在尝试从HTML表格中显示的一系列频道中选择一个频道。我正在使用以下Selenium方法来选择链接

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

然而,它正在选择列表中的第一个频道(帐户管理)。我希望它会选择正确的通道或抛出错误,而不是选择错误的通道。以下是我想要的频道的完整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>

3 个答案:

答案 0 :(得分:2)

首先 - 你的错误!

您忘记了“销售”周围的引号,只需更改一下代码就可以了:

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

第二个 - xpath bug?

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

它实际上击中了所有三个跨度项目。因为您使用了findElement函数,所以只能获得第一个结果。

试试这个,你会看到怪癖:

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

结果将是:

  

3

第三 - 可能是“按设计”

看一下w3c definition,你会发现以下一行:

  

如果$ arg2的值是零长度字符串,那么该函数   返回true。

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

  

如果参数不是string类型,则首先将其转换为a   字符串,然后评估。

将所有这些信息放在一起,我想,xpath将非字符串/非变量第二个参数解释为空字符串,因此在搜索//span以来所有span元素都返回true。

更新

来自@MichaelKay的评论我们得知,我的“猜测”非常接近:

  

在XPath和XQuery中,像“hello”这样的裸名称表示child :: hello,和   如果你没有使用模式感知,那么系统只会看   对于叫做你好的孩子,如果没有,它会返回一个   空节点集。

结论:OP看到的行为与设计一致,即使它看起来非常不直观。

答案 1 :(得分:1)

您正在使用的xpath缺少""文本周围的引号Salestext()函数接受一个字符串参数,并且可以使用引号形成字符串。以下列方式更新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();

希望这有帮助。

答案 2 :(得分:1)

需要将xpath修改为“// span [contains(text(),'Sales')]”。

正如我们在下面的方法定义中看到的那样,contains方法只返回true如果第二个参数也是文本。

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

包含(s1,s2) 如果s1包含s2,则返回true。 文本() 找到text类型的节点