xpath路徑選擇器定位元素
1. xpath:
使用路徑表達式來定位xml或者html中文檔中選取節點。在 XPath 中,有七種類型的節點:元素、屬性、文本、命名空間、處理指令、注釋以及文檔節點(或稱為根節點)
假設xml文檔為:
<?xml version="1.0" encoding="ISO-8859-1"?>
<bookstore>
<book>
<title lang="en">Harry Potter</title>
<author>J K. Rowling</author>
<year>2005</year>
<price>29.99</price>
</book>
</bookstore>
l 文檔節點:<bookstore>
l 元素節點:<author>J K. Rowling</author>
l 屬性節點:lang="en"
l 文本:2005
l 父節點(Parent):每個元素以及屬性都有一個父。book 元素是 title、author、year 以及 price 元素的父
l 子節點(Children):節點可有零個、一個或多個子節點。title、author、year 以及 price 元素都是 book 元素的子
l 同胞(Sibling):擁有相同的父的節點。title、author、year 以及 price 元素都是同胞
l 先輩(Ancestor):某節點的父、父的父,等等。title 元素的先輩是 book 元素和 bookstore 元素
l 后代(Descendant):某個節點的子,子的子,等等。bookstore 的后代是 book、title、author、year 以及 price 元素
2. 基礎語法:
1) 路徑表達式
表達式 |
描述 |
nodename |
選取此節點的所有子節點。 |
/ |
從根節點選取。(可以理解為后面跟的是絕對路徑) |
// |
從匹配選擇的當前節點選擇文檔中的節點,而不考慮它們的位置。(相對路徑) |
. |
選取當前節點。 |
.. |
選取當前節點的父節點。 |
@ |
選取屬性。后面跟屬性名 |
2) 謂語(Predicates)
放在方括號[]中,相當於篩選條件,用來查找[]中指定的特定節點或者包含某個指定的值的節點。在下面的表格中,列出了帶有謂語的一些路徑表達式,以及表達式的結果:
路徑表達式 |
結果 |
/bookstore/book[1] |
選取屬於 bookstore 子元素的第一個 book 元素。 /表示絕對路徑,所以后面跟的是根節點bookstore,[]內部的數字表示第幾個[]前面的元素,也就是第1個book元素,注意這里的編號是從1開始。 |
/bookstore/book[last()] |
選取屬於 bookstore 子元素的最后一個 book 元素。 |
/bookstore/book[last()-1] |
選取屬於 bookstore 子元素的倒數第二個 book 元素。 |
/bookstore/book[position()<3] |
選取最前面的兩個屬於 bookstore 元素的子元素的 book 元素。 |
//title[@lang] |
@lang表示lang屬性,//title表示選取所有title元素,這個表達式表示的是選取所有帶 lang 屬性的 title 元素。 |
//title[@lang='eng'] |
選取所有 title 元素,且元素的lang屬性值為eng |
/bookstore/book[price>35.00] |
選取 bookstore 元素的所有 book 元素,且其中的 price 元素的值須大於 35.00。 |
/bookstore/book[price>35.00]/title |
選取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值須大於 35.00。 |
XPath 通配符可用來選取未知的 XML 元素。
通配符 |
描述 |
* |
匹配任何元素節點。 |
@* |
匹配任何屬性節點。 |
node() |
匹配任何類型的節點。 |
在下面的表格中,列出了一些路徑表達式,以及這些表達式的結果:
路徑表達式 |
結果 |
/bookstore/* |
選取 bookstore 元素的所有子元素。 |
//* |
選取文檔中的所有元素。 |
//title[@*] |
選取所有帶有屬性的 title 元素。 |
3) xpath軸
親屬關系匹配
例子 |
結果 |
/bookstore/child::book |
child表示子節點,child::book就是子節點名為book的節點,整個表達式就是說bookstore節點的所有子節點名字為book的節點 |
attribute::lang |
attribute表示屬性名,表達式為選取當前節點的 lang 屬性。 |
child::* |
選取當前節點的所有子元素。 |
attribute::* |
選取當前節點的所有屬性。 |
child::text() |
選取當前節點的所有文本子節點。 |
child::node() |
選取當前節點的所有子節點。 |
descendant::book |
選取當前節點的所有 book 后代。 |
ancestor::book |
選擇當前節點的所有 book 先輩。 |
ancestor-or-self::book |
選取當前節點的所有 book 先輩以及當前節點(如果此節點是 book 節點) |
child::*/child::price |
選取當前節點的所有 price 孫節點。 |
parent::* |
找到父級元素 |
following::* |
選取文檔中當前節點的結束標簽之后的所有節點 |
preceding::* |
選取文檔中當前節點的開始標簽之前的所有節點。 |
preceding-sibling::* |
選取當前節點之前的所有同級節點 |
following-sibling::* |
選取當前節點之后的所有同級節點 |
descendant::* |
選取當前節點的所有后代元素(子、孫等) |
例如有一段html的內容如下
<div>
<span>text</span>
<input id = ‘123’>
</div>
此時如果想要獲取第二個span標簽,可以這樣寫:
//input[@id='123']/preceding-sibling::span
input標簽比較好找,先找到input標簽,然后找它的兄弟節點。preceding-sibling表示找前面的元素的同級元素,后面的::span表示找的是span標簽。
4) Xpath運算符
在下面的表格中,我們列出了一些路徑表達式,以及這些表達式的結果:
路徑表達式 |
結果 |
//book/title | //book/price |
選取 book 元素的所有 title 和 price 元素。 |
//title | //price |
選取文檔中的所有 title 和 price 元素。 |
/bookstore/book/title | //price |
選取屬於 bookstore 元素的 book 元素的所有 title 元素,以及文檔中所有的 price 元素。 |
5) xpath常用函數
實例 |
返回值 |
last() |
返回當前上下文中的最后一個節點的位置號碼數 |
position() |
返回當前節點的位置的數字,位於第多少個 |
//book[position()=2]等價於//book[2]
例子:
路徑表達式 |
結果 |
//div[last()] |
最后一個div |
//div[last()-1] |
倒數第二個div |
//div[position()<3] |
前兩個div |
//div[@id='id3']//p[last()] |
第三個div中最后一個p標簽對象 |
//div[@href='http://www.baidu.com'] |
選取連接為http://www.baidu.com的屬性 |
//*[@id='id3']//p[contain(.,'20')] |
在第3個div中找包含20的文本節點 |
//*[@id='id3']//p[contain(.,'20')]//fowing-sibiling::p |
選取包含字符串20文本節點的下一個節點的p節點 |
3. 補充幾個常用方法
3.1 contains
包含,比如//div[contains(@class,'xx')]
查找div元素,元素的class屬性值包含xx
3.2 starts-with
以某某開頭,例如
//input[starts-with(@class,'xx')]
查找input元素,元素的class屬性值以xx開頭
3.3 ends-with
以某某結尾,例如:
//input[starts-with(@class,'xx')]
查找input元素,元素的class屬性值以xx結尾
3.4 not
否定的意思,比如:
input[not(id='123')]
查找id值不是123的input元素。
//span[not(contains(text(),'123'))]
查找一個文本內容不包含123的span標簽。
3.5 *通配符
*表示通配符,比如://span[@*='123']
span標簽的任何屬性為123的元素
4. 定位原則
以百度首頁為例
1) 用id定位,比如//input[@id="su"]
2) 用元素文本 比如//input[@value="百度一下"]
3) 用元素的唯一屬性,找到這個元素的唯一屬性,寫法同上
4) 用元素的多個屬性組合,比如//*[@id="kw" and @name ="wd"]
5) contains模糊匹配,比如//div[@id="u"]/a[contains(.,"錄")]。或者可以寫//div[@id="u"]/a[contains(@href,"passport")]
6) 找到已查找的元素,然后基於此元素的相對位置定位,比如先找到一個div,再通過找到的這個div找他的父親或者兄弟,子女。//div[@id="u"]/child::node(),先找到一個id屬性為u的div,再找到這個div的所有孩子節點,后面跟[1],就是這些孩子節點的第一個節點。