2015-10-04 85 views
0

我試圖從一系列顯示在HTML表格中的通道中選擇一個通道。我用下面的方法硒選擇鏈接Selenium通過Xpath查找返回錯誤的元素

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> 

回答

1

中的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(); 

希望這會有所幫助。

+0

哇,我現在覺得很愚蠢!我認爲長久以來看它讓我錯過了顯而易見的事實。非常感謝。 – adohertyd

2

首先 - 你的錯誤!

你忘了周圍的「銷售」的引號,只要改變你的代碼了一下,它會工作:

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

二 - XPath的錯誤嗎?

你說得對,它很奇怪,你沒有收到錯誤信息,而是第一個是跨度的元素。 這可能會成爲xpath中的一個bug。 contains函數意識到你的第二個參數不是一個字符串,而是返回false,它返回true

它實際上擊中了所有三個跨度項目。因爲您使用了findElement函數,所以只能得到第一個結果。

試試這個,你會看到怪癖:

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

結果將是:

三 - 可能是 「作爲設計的」

有看看w3c definition你會發現下面這行:

如果$ arg2的值是零長度字符串,則函數 返回true。

然後在xpath-site of microsoft你會發現另一個有趣的提示拼圖:

如果參數是字符串類型,它都首先被轉換爲 字符串,然後進行評估。

一起把所有這些信息,我想,XPath的解釋你的非字符串/不可變的第二個參數爲空字符串,因此所有的span元素返回true,因爲你正在尋找//span

UPDATE

從@MichaelKay在我們學習的意見,我的「猜測」是八九不離十:

在XPath和XQuery,裸露的名稱,如「你好」是指孩子::你好和 如果您沒有使用模式感知,那麼系統將爲名爲hello的孩子查找 ,如果沒有,則會返回一個空節點集 。

結論:OP看到的行爲與設計一樣,即使它看起來非常不直觀。

+0

是的,如果contains()的第二個參數是一個空節點集合,那麼答案將始終爲真。 –

+0

@MichaelKay,是的,仍然會很有趣,爲什麼這裏的這個「非字符串」被解釋爲一個空的節點集,並且不僅僅是一種表示錯誤並因此返回false的方式。或者更好地返回一個異常,通常發生在缺少xquery中的角色時。 – drkthng

+1

在XPath和XQuery中,像「hello」這樣的名字意味着'child :: hello',如果你沒有使用模式感知,那麼系統只會尋找名爲'hello'的孩子,如果沒有'任何,它將返回一個空的節點集。那是你問的嗎? –

1

xpath需要修改爲「// span [contains(text(),'Sales')]」。

正如我們在下面的方法定義中所看到的,contains方法將只返回true如果第二個參數也是一個文本。

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

含有(S1,S2) 返回true如果s1包含S2。 text() 找到一個類型爲文字的節點

相關問題