源文http://www.cnblogs.com/qingchunjun/p/4208159.html
By.xpath()
這個方法是非常強大的元素查找方式,使用這種方法幾乎可以定位到頁面上的任意元素。在正式開始使用XPath進行定位前,我們先了解下什么是 XPath。XPath是XML Path的簡稱,由於HTML文檔本身就是一個標准的XML頁面,所以我們可以使用XPath的語法來定位頁面元素。
假設我們現在以圖(2)所示HTML代碼為例,要引用對應的對象,XPath語法如下:
圖(2)
絕對路徑寫法(只有一種),寫法如下:
引用頁面上的form元素(即源碼中的第3行):/html/body/form[1]
注意:1. 元素的xpath絕對路徑可通過firebug直接查詢。2. 一般不推薦使用絕對路徑的寫法,因為一旦頁面結構發生變化,該路徑也隨之失效,必須重新寫。3. 絕 對路徑以單/號表示,而下面要講的相對路徑則以//表示,這個區別非常重要。另外需要多說一句的是,當xpath的路徑以/開頭時,表示讓Xpath解析 引擎從文檔的根節點開始解析。當xpath路徑以//開頭時,則表示讓xpath引擎從文檔的任意符合的元素節點開始進行解析。而當/出現在xpath路 徑中時,則表示尋找父節點的直接子節點,當//出現在xpath路徑中時,表示尋找父節點下任意符合條件的子節點,不管嵌套了多少層級(這些下面都有例 子,大家可以參照來試驗)。弄清這個原則,就可以理解其實xpath的路徑可以絕對路徑和相對路徑混合在一起來進行表示,想怎么玩就怎么玩。
下面是相對路徑的引用寫法:
查找頁面根元素://
查找頁面上所有的input元素://input
查找頁面上第一個form元素內的直接子input元素(即只包括form元素的下一級input元素,使用絕對路徑表示,單/號)://form[1]/input
查找頁面上第一個form元素內的所有子input元素(只要在form元素內的input都算,不管還嵌套了多少個其他標簽,使用相對路徑表示,雙//號)://form[1]//input
查找頁面上第一個form元素://form[1]
查找頁面上id為loginForm的form元素://form[@id='loginForm']
查找頁面上具有name屬性為username的input元素://input[@name='username']
查找頁面上id為loginForm的form元素下的第一個input元素://form[@id='loginForm']/input[1]
查找頁面具有name屬性為contiune並且type屬性為button的input元素://input[@name='continue'][@type='button']
查找頁面上id為loginForm的form元素下第4個input元素://form[@id='loginForm']/input[4]
Xpath功能很強大,所以也可以寫得更加復雜一些,如下面圖(3)的HTML源碼。
圖(3)
如果我們現在要引用id為“J_password”的input元素,該怎么寫呢?我們可以像下面這樣寫:
WebElement password = driver.findElement(By.xpath("//*[@id='J_login_form']/dl/dt/input[@id='J_password']"));
也可以寫成:
WebElement password = driver.findElement(By.xpath("//*[@id='J_login_form']/*/*/input[@id='J_password']"));
這里解釋一下,其中//*[@id=’ J_login_form’]這一段是指在根元素下查找任意id為J_login_form的元素,此時相當於引用到了form元素。后面的路徑必須按照 源碼的層級依次往下寫。按照圖(3)所示代碼中,我們要找的input元素包含在一個dt標簽內,而dt又包含在dl標簽內,所以中間必須寫上dl和dt 兩層,才到input這層。當然我們也可以用*號省略具體的標簽名稱,但元素的層級關系必須體現出來,比如我們不能寫成//* [@id='J_login_form']/input[@id='J_password'],這樣肯定會報錯的。
前面講的都是xpath中基於准確元素屬性的定位,其實xpath作為定位神器也可以用於模糊匹配。比如下面圖(4)所示代碼:
圖(4)
這段代碼中的“退出”這個超鏈接,沒有標准id元素,只有一個rel和href,不是很好定位。不妨我們就用xpath的幾種模糊匹配模式來定位它吧,主要有三種方式,舉例如下。
a. 用contains關鍵字,定位代碼如下:
1 driver.findElement(By.xpath(“//a[contains(@href, ‘logout’)]”));
這句話的意思是尋找頁面中href屬性值包含有logout這個單詞的所有a元素,由於這個退出按鈕的href屬性里肯定會包含logout,所以這種方式是可行的,也會經常用到。其中@后面可以跟該元素任意的屬性名。
b. 用start-with,定位代碼如下:
1 driver.findElement(By.xpath(“//a[starts-with(@rel, ‘nofo’)]));
這句的意思是尋找rel屬性以nofo開頭的a元素。其中@后面的rel可以替換成元素的任意其他屬性。
c. 用Text關鍵字,定位代碼如下:
1 driver.findElement(By.xpath(“//*[text()=’退出’]));
這個方法可謂相當霸氣啊。直接查找頁面當中所有的退出二字,根本就不用知道它是個a元素了。這種方法也經常用於純文字的查找。
另外,如果知道超鏈接元素的文本內容,也可以用
1 driver.findElement(By.xpath(“//a[contains(text(), ’退出’)]));
這種方式一般用於知道超鏈接上顯示的部分或全部文本信息時,可以使用。
最后,關於xpath這種定位方式,webdriver會將整個頁面的所有元素進行掃描以定位我們所需要的元素,所以這是一個非常費時的操作,如果你的腳本中大量使用xpath做元素定位的話,將導致你的腳本執行速度大大降低,所以請慎用。
