網頁元素定位神器之Xpath詳解

摘要: 常常在工做中會使用到XPath的相關知識,但每次總會在一些關鍵的地方不記得或不太清楚,因此免不了每次總要查一些零碎的知識,感受即很煩又浪費時間,因此對XPath概括及總結一下。 ...
 
 

常常在工做中會使用到XPath的相關知識,但每次總會在一些關鍵的地方不記得或不太清楚,因此免不了每次總要查一些零碎的知識,感受即很煩又浪費時間,因此對XPath概括及總結一下。node

在這篇文章中你將能學習到:函數

  • XPath簡介
  • XPath 路徑表達式詳解
  • XPath在DOM,XSLT及XQuery中的應用

XPath簡介學習

XPath是W3C的一個標準。它最主要的目的是爲了在XML1.0或XML1.1文檔節點樹中定位節點所設計。目前有XPath1.0和XPath2.0兩個版本。其中Xpath1.0是1999年成爲W3C標準,而XPath2.0標準的確立是在2007年。W3C關於XPath的英文詳細文檔請見:http://www.w3.org/TR/xpath20/ 。測試

 

XPath是一種表達式語言,它的返回值多是節點,節點集合,原子值,以及節點和原子值的混合等。XPath2.0是XPath1.0的超集。它是對XPath1.0的擴展,它能夠支持更加豐富的數據類型,而且XPath2.0保持了對XPath1.0的相對很好的向後兼容性,幾乎全部的XPath2.0的返回結果均可以和XPath1.0保持同樣。另外XPath2.0也是XSLT2.0和XQuery1.0的用於查詢定位節點的主表達式語言。XQuery1.0是對XPath2.0的擴展。關於在XSLT和XQuery中使用XPath表達式定位節點的知識在後面的實例中會有所介紹。spa

 

在學習XPath以前你應該對XML的節點,元素,屬性,原子值(文本),處理指令,註釋,根節點(文檔節點),命名空間以及對節點間的關係如:父(Parent),子(Children),兄弟(Sibling),先輩(Ancestor),後代(Descendant)等概念有所瞭解。這裏不在說明。設計

 

XPath路徑表達式遞歸

在本小節下面的內容中你將能夠學習到:索引

  • 路徑表達式語法
  • 相對/絕對路徑
  • 表達式上下文
  • 謂詞(篩選表達式)及軸的概念
  • 運算符及特殊字符
  • 經常使用表達式實例
  • 函數及說明

這裏給出一個實例Xml文件。下面的說明及實例都是基於該XML文件。ip

  1. 路徑表達式語法:

     

    1. 路徑 = 相對路徑 | 絕對路徑
    2. XPath路徑表達式 = 步進表達式 | 相對路徑 "/"步進表達式。
    3. 步進表達式=軸 節點測試 謂詞

說明:ci

  1. 其中軸表示步進表達式選擇的節點和當前上下文節點間的樹狀關係(層次關係),節點測試指定步進表達式選擇的節點名稱擴展名,謂詞即至關於過濾表達式以進一步過濾細化節點集。
  2. 謂詞能夠是0個或多個。多個多個謂詞用邏輯操做符and, or鏈接。取邏輯非用not()函數。

請看一個典型的XPath查詢表達式:/messages/message//child::node()[@id=0],其中/messages/message是路徑(絕對路徑以"/"開始),child::是軸表示在子節點下選擇,node()是節點測試表示選擇全部的節點。[@id=0]是謂詞,表示選擇全部有屬性id而且值爲0的節點。

  1. 相對路徑與絕對路徑:

若是"/"處在XPath表達式開頭則表示文檔根元素,(表達式中間做爲分隔符用以分割每個步進表達式)如:/messages/message/subject是一種絕對路徑表示法,它代表是從文檔根開始查找節點。假設當前節點是在第一個message節點【/messages/message[1]】,則路徑表達式subject(路徑前沒有"/")這種表示法稱爲相對路徑,代表從當前節點開始查找。具體請見下面所述的"表達式上下文"。

 

  1. 表達式上下文(Context):

上下文其實表示一種環境。以明確當前XPath路徑表達式處在什麼樣的環境下執行。例如一樣一個路徑表達式處在對根節點操做的環境和處在對某一個特定子節點操做的環境下執行所得到的結果多是徹底不同的。也就是說XPath路徑表達式計算結果取決於它所處的上下文。

 

XPath上下文基本有如下幾種:

  • 當前節點(./):

    如./sender表示選擇當前節點下的sender節點集合(等同於下面所講的"特定元素",如:sender)

  • 父節點(../):

    如../sender表示選擇當前節點的父節點下的sender節點集合

  • 根元素(/):

    如/messages表示選擇從文檔根節點下的messages節點集合.

  • 根節點(/*):

    這裏的*是表明全部節點,可是根元素只有一個,因此這裏表示根節點。/*的返回結果和/messages返回的結果同樣都是messages節點。

  • 遞歸降低(//):

    如當前上下文是messages節點。則//sender將返回如下結果:

    /messages//sender :

    <sender>gkt1980@gmail.com</sender>

    <sender>111@gmail.com</sender>

    <sender>333@gmail.com</sender>

     

    /messages/message[1]//sender:

    <sender>gkt1980@gmail.com</sender>

    <sender>111@gmail.com</sender>

     

    咱們能夠看出XPath表達式返回的結果是:從當前節點開始遞歸步進搜索當前節點下的全部子節點找到知足條件的節點集。

     

  • 特定元素

    如sender:表示選擇當前節點下的sender節點集合,等同於(./sender)

注意:在執行XPath時必定要注意上下文。即當前是在哪一個節點下執行XPath表達式。這在XMLDOM中很重要。如:在XMLDOM中的selectNodes,selectSingleNode方法的參數都是一個XPath表達式,此時這個XPath表達式的執行上下文就是調用這個方法的節點及它所在的環境。更多信息請參見:http://www.w3.org/TR/xpath20/

  1. 謂詞(篩選表達式)及軸的概念:

XPath的謂詞即篩選表達式,相似於SQL的where子句.

軸名稱

結果

ancestor

選取當前節點的全部先輩(父、祖父等)

ancestor-or-self

選取當前節點的全部先輩(父、祖父等)以及當前節點自己

attribute

選取當前節點的全部屬性

child

選取當前節點的全部子元素。

descendant

選取當前節點的全部後代元素(子、孫等)。

descendant-or-self

選取當前節點的全部後代元素(子、孫等)以及當前節點自己。

following

選取文檔中當前節點的結束標籤以後的全部節點。

namespace

選取當前節點的全部命名空間節點

parent

選取當前節點的父節點。

preceding

直到全部這個節點的父輩節點,順序選擇每一個父輩節點前的全部同級節點

preceding-sibling

選取當前節點以前的全部同級節點。

self

選取當前節點。

 

  1. 運算符及特殊字符:

運算符/特殊字符

說明

/

此路徑運算符出如今模式開頭時,表示應從根節點選擇。

//

從當前節點開始遞歸降低,此路徑運算符出如今模式開頭時,表示應從根節點遞歸降低。

.

當前上下文。

..

當前上下文節點父級。

*

通配符;選擇全部元素節點與元素名無關。(不包括文本,註釋,指令等節點,若是也要包含這些節點請用node()函數)

@

屬性名的前綴。

@*

選擇全部屬性,與名稱無關。

:

命名空間分隔符;將命名空間前綴與元素名或屬性名分隔。

( )

括號運算符(優先級最高),強制運算優先級。

[ ]

應用篩選模式(即謂詞,包括"過濾表達式"和"軸(向前/向後)")。

[ ]

下標運算符;用於在集合中編制索引。

|

兩個節點集合的聯合,如://messages/message/to | //messages/message/cc

-

減法。

div,

浮點除法。

and, or

邏輯運算。

mod

求餘。

not()

邏輯非

=

等於

!=

不等於

特殊比較運算符

< 或者 &lt;

<= 或者 &lt;=

> 或者 &gt;

>= 或者 &gt;=

須要轉義的時候必須使用轉義的形式,如在XSLT中,而在XMLDOM的scripting中不須要轉義。

 

  1. 經常使用表達式實例:

     

/

Document Root文檔根.

/*

選擇文檔根下面的全部元素節點,即根節點(XML文檔只有一個根節點)

/node()

根元素下全部的節點(包括文本節點,註釋節點等)

/text()

查找文檔根節點下的全部文本節點

/messages/message

messages節點下的全部message節點

/messages/message[1]

messages節點下的第一個message節點

/messages/message[1]/self::node()

第一個message節點(self軸表示自身,node()表示選擇全部節點)

/messages/message[1]/node()

第一個message節點下的全部子節點

/messages/message[1]/*[last()]

第一個message節點的最後一個子節點

/messages/message[1]/[last()]

Error,謂詞前必須是節點或節點集

/messages/message[1]/node()[last()]

第一個message節點的最後一個子節點

/messages/message[1]/text()

第一個message節點的全部子節點

/messages/message[1]//text()

第一個message節點下遞歸降低查找全部的文本節點(無限深度)

/messages/message[1] /child::node()

/messages/message[1] /node()

/messages/message[position()=1]/node()

//message[@id=1] /node()

第一個message節點下的全部子節點

//message[@id=1] //child::node()

遞歸全部子節點(無限深度)

//message[position()=1]/node()

選擇id=1的message節點以及id=0的message節點

/messages/message[1] /parent::*

Messages節點

相關文章
相關標籤/搜索