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表達式定位節點的知識在後面的實例中會有所介紹。
在學習XPath之前你應該對XML的節點,元素,屬性,原子值(文本),處理指令,注釋,根節點(文檔節點),命名空間以及對節點間的關系如:父(Parent),子(Children),兄弟(Sibling),先輩(Ancestor),後代(Descendant)等概念有所了解。這裡不在說明。
XPath路徑表達式
在本小節下面的內容中你將可以學習到:
這裡給出一個實例Xml文件。下面的說明及實例都是基於該XML文件。
路徑表達式語法:
說明:
運算符及特殊字符: 運算符/特殊字符 說明 / 此路徑運算符出現在模式開頭時,表示應從根節點選擇。 // 從當前節點開始遞歸下降,此路徑運算符出現在模式開頭時,表示應從根節點遞歸下降。 . 當前上下文。 .. 當前上下文節點父級。 * 通配符;選擇所有元素節點與元素名無關。(不包括文本,注釋,指令等節點,如果也要包含這些節點請用node()函數) @ 屬性名的前綴。 @* 選擇所有屬性,與名稱無關。 : 命名空間分隔符;將命名空間前綴與元素名或屬性名分隔。 ( ) 括號運算符(優先級最高),強制運算優先級。 [ ] 應用篩選模式(即謂詞,包括"過濾表達式"和"軸(向前/向後)")。 [ ] 下標運算符;用於在集合中編制索引。 | 兩個節點集合的聯合,如://messages/message/to | //messages/message/cc - 減法。 div, 浮點除法。 and, or 邏輯運算。 mod 求余。 not() 邏輯非 = 等於 != 不等於 特殊比較運算符 < 或者 < <= 或者 <= > 或者 > >= 或者 >= 需要轉義的時候必須使用轉義的形式,如在XSLT中,而在XMLDOM的scripting中不需要轉義。
常用表達式實例: / 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節點 /messages/message[1]/body/attachments/parent::node() /messages/message[1]/body/attachments/parent::* /messages/message[1]/body/attachments/.. attachments節點的父節點。父節點只有一個,所以node()和* 返回結果一樣。 (..也表示父節點. 表示自身節點) //message[@id=0]/ancestor::* Ancestor軸表示所有的祖輩,父,祖父等。 向上遞歸 //message[@id=0]/ancestor-or-self::* 向上遞歸,包含自身 //message[@id=0]/ancestor::node() 對比使用*,多一個文檔根元素(Document root) /messages/message[1]/descendant::node() //messages/message[1]//node() 遞歸下降查找message節點的所有節點 /messages/message[1]/sender/following::* 查找第一個message節點的sender節點後的所有同級節點,並對每一個同級節點遞歸向下查找。 //message[@id=1]/sender/following-sibling::* 查找id=1的message節點的sender節點的所有後續的同級節點。 //message[@id=1]/datetime/@date 查找id=1的message節點的datetime節點的date屬性 //message[@id=1]/datetime[@date] //message/datetime[attribute::date] 查找id=1的message節點的所有含有date屬性的datetime節點 //message[datetime] 查找所有含有datetime節點的message節點 //message/datetime/attribute::* //message/datetime/attribute::node() //message/datetime/@* 返回message節點下datetime節點的所有屬性節點 //message/datetime[attribute::*] //message/datetime[attribute::node()] //message/datetime[@*] //message/datetime[@node()] 選擇所有含有屬性的datetime節點 //attribute::* 選擇根節點下的所有屬性節點 //message[@id=0]/body/preceding::node() 順序選擇body節點所在節點前的所有同級節點。(查找順序為:先找到body節點的頂級節點(根節點),得到根節點標簽前的所有同級節點,執行完成後繼續向下一級,順序得到該節點標簽前的所有同級節點,依次類推。) 注意:查找同級節點是順序查找,而不是遞歸查找。 //message[@id=0]/body/preceding-sibling::node() 順序查找body標簽前的所有同級節點。(和上例一個最大的區別是:不從最頂層開始到body節點逐層查找。我們可以理解成少了一個循環,而只查找當前節點前的同級節點) //message[@id=1]//*[namespace::amazon] 查找id=1的所有message節點下的所有命名空間為amazon的節點。 //namespace::* 文檔中的所有的命名空間節點。(包括默認命名空間xmlns:xml) //message[@id=0]//books/*[local-name()='book'] 選擇books下的所有的book節點, 注意:由於book節點定義了命名空間<amazone:book>.若寫成//message[@id=0]//books/book則查找不出任何節點。 //message[@id=0]//books/*[local-name()='book' and namespace-uri()='http://www.amazon.com/books/schema'] 選擇books下的所有的book節點,(節點名和命名空間都匹配) //message[@id=0]//books/*[local-name()='book'][year>2006] 選擇year節點值>2006的book節點 //message[@id=0]//books/*[local-name()='book'][1]/year>2006 指示第一個book節點的year節點值是否大於2006. 返回xs:boolean: true
函數及說明: 值得欣喜的是XPath函數和XSLT,XQuery等共享函數庫,函數庫為我們提供了功能豐富的各種函數的調用,我們也可以自定義自己的函數。這裡不再對每個函數的用法逐一說明,英文好點的朋友直接去看看w3關於XPath函數的介紹吧:http://www.w3.org/TR/xquery-operators 。中文的可以參考這個網站, http://www.w3school.com.cn/xpath/xpath_functions.asp XPath在DOM,XSLT及XQuery中的應用 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">