XPath
XPath 簡介
XPath 是一門在 XML 文檔中查找信息的語言。XPath 可用來在 XML 文檔中對元素和屬性進行遍歷。XPath 是 W3C XSLT 標准的主要元素,並且 XQuery 和 XPointer 同時被構建於 XPath 表達之上。因此,對 XPath 的理解是很多高級 XML 應用的基礎。 其實對些我們並不陌生,最與XPath相似的便是CSS的選擇器.在CSS中使用CSS選擇符選擇元素來應用樣式,而在XSLT中則使用XPath,XPath與CSS選擇器相比如強大的許多!下面是CSS選擇符與XPath選擇符一些對照:
//CSS選擇符 body p //選擇所有body下面的p元素 body>p //選擇body的子元素p * //選擇所有的元素 //與之對應的XPath選擇符 body//p body/p *
雖然現在還不能了解這些XPath表達的含意,但可以發現,它和CSS選擇符十分相像!但XPath有更強大的地方,比如它可以定位到body元素下具體位置上的p或可以選擇前N個p:
body/p[position()=4] //這個XPath表達式將選取body子元素中第4個p元素,注意這里從1開始計數 body/p[position()<3] //將選取body子元素中前兩個p元素
XPath 使用路徑表達式來選取 XML 文檔中的節點或者節點集。這些路徑表達式和我們在常規的電腦文件系統中看到的表達式非常相似。另外,XPath 含有超過 100 個內建的函數。這些函數用於字符串值、數值,日期和時間比較、節點和 QName 處理、序列處理、邏輯值等等。
書寫XPath
XPath使用路徑表達式在 XML 文檔中選取節點。節點是通過沿着路徑(path)或者 步(step) 來選取的。如"/"表示文檔節點,"."表示當前節點,而".."則表示當前節點的父節點.示例:
{因為XPath表示達式中有斜杠,所以暫時用這個表示注釋! / {選取文檔節點,nodeType為9 /root {選取文檔根元素,類似於文件系統的路徑(Unix),以/開頭的路徑都是絕對路徑 /root/child/.. {選取根節點root的子節點child的父節點(就是root)
下面是一些常用路徑表達式
- nodeName 選取名稱為nodeName的節點
- / 從根節點選取
- // 選擇元素后代元素,必須在后面跟上nodeName
- . 選取當前節點
- .. 選取當前節點的父節點
- @ 選取屬性節點(@是attribute的縮寫)
<?xml version="1.0"?> <root> <child attr="attr" /> <child> <a><desc /></a> </child> </root> {針對上面的XML文檔的XPath結果,當前節點為document /root {選取root root {選取root child {空,因為child不是document的子元素 //child {選取兩個child元素,//表示后代 //@attr {選取attr屬性節點 /root/child//desc {返回child的后代元素desc
謂語(Predicates)
謂語用於在查找節點時提供更詳盡的信息,謂語被嵌在方括號中。下面是一些帶有謂語的XPath表達式:
/root/child[3] {選取root元素的第三個child子元素,注意,這和數組下標不一樣,從1開始計數 //child[@attr] {選取所有具有屬性attr的child元素 //child[@attr="val"]/desc {選取所有屬性attr的值為val的child元素的子元素desc //child[desc] {選取所有的有desc子元素的child //child[position()>3] {position()是XPath中的一個函數,表示節點的位置 //child[@attr>12] {XPath表達式還可以進行數值比較,該表達式將選取attr屬性值大於12的child元素 //child[last()] {last()函數返回節點列表最后的位置,該表達式將選取最后一個child元素
通配符
XPath 通配符可用來選取未知的 XML 元素。
- * ,和CSS中的選擇符一樣,這將匹配任何元素節點
- @* ,匹配任何屬性節點
- node() ,匹配任何類型的節點
/root/* {選取根元素下面的所有子元素 /root/node() {選取根元素下面的所有節點,包括文本節點 //* {選取文檔中所有元素 //child[@*] {選取所有具有屬性的child元素 //@* {選取所有的屬性節點
組合路徑
與CSS中使用逗號組合使用多個選擇符一樣,XPath支持一種使用"|"來組合多個路徑的語法!
/root | /root/child {選取根元素root與它下面的子元素child //child | //desc {選取所有的child元素與desc元素
XPath 運算符
下面列出了可用在 XPath 表達式中的運算符:
- | ,計算兩個節點集
- + ,加法
- - ,減法
- * ,乘法
- div ,除法,因為/已經被作為路徑符了,所以不能用來作為除法標識
- mod ,取余
- = ,等於
- != ,不等於
- < ,小於
- <= ,小於或等於
- > ,大於
- >= ,大於或等於
- or ,或
- and ,與
XPath 軸
軸可定義某個相對於當前節點的節點集。下面一可用的軸名稱與對應的結果:
- ancestor 選取當前節點的所有先輩(父、祖父等)
- ancestor-or-self 選取當前節點的所有先輩(父、祖父等)以及當前節點本身
- attribute 選取當前節點的所有屬性
- child 選取當前節點的所有子元素。
- descendant 選取當前節點的所有后代元素(子、孫等)。
- descendant-or-self 選取當前節點的所有后代元素(子、孫等)以及當前節點本身。
- following 選取文檔中當前節點的結束標簽之后的所有節點。
- namespace 選取當前節點的所有命名空間節點
- parent 選取當前節點的父節點。
- preceding 選取文檔中當前節點的開始標簽之前的所有節點。
- preceding-sibling 選取當前節點之前的所有同級節點。
- self 選取當前節點。
事實上,一個完整的XPath表達式由"/"與"步"構成的,而步又是由 "軸" 、 "節點測試"和"謂語"構成的.如下:
step/step/..... {一個XPath表達式 {step的構成 軸名稱::節點測試[謂語]
在一般的XPath表達式中,沒有謂語即表達沒有其它條件限制,而沒有軸名稱,則默認使用child.如"abc"與"child::abc"是等效的, 下面是一些與使用軸名稱等效的簡單XPath表達式:
- child::abc --------------------- abc(子元素abc)
- root/attribute::id ------------ root/@id(root的屬性id)
- selft::node() ------------------ .(自身)
- parent::node() --------------- ..(父節點)
- child::* ------------------------ *(子元素)
- child::text() ------------------ text()(子文本節點)
- descendant::tag ------------ .//tag (后代tag元素)
XPath還包含一套函數庫,如position與last就是函數,一般的函數被用在謂語中,而在XSLT及XQuery中它們則得到了更廣泛的使用.
瀏覽器中的XPath
IE瀏覽器對XPath的實現比較簡單.一個XML DOM對象(及每個節點)都有selectSingleNode與selectNodes方法,傳入XPath表達式,selectNodes返回匹配的節點列表,而selectSingleNode則只返回列表中第一個項目!
var xmlDom = getXMLDOM();//我們之前寫的跨瀏覽器的XML DOM加載函數 loadXMLFile(xmlDom,"text.xml"); var root = xmlDom.selectSingleNode("/*");//返回文檔根元素 root = xmlDom.selectNodes("/*")[0];//同上 var lastChild = xmlDom.selectSingleNode("/*/*[last()]");
Mozilla是根據DOM標准來實現對XPath的支持的。DOM Level 3附加標准DOM Level 3 XPath定義了用於在DOM中計算XPath表達式的接口。遺憾的是,這個標准要比微軟直觀的方式復雜得多。
雖然有好多與XPath相關的對象,最重要的兩個是:XPathEvaluator和XPathResult。XPathEvaluator利用方法evaluate()計算XPath表達式。
evaluate()方法有五個參數:XPath表達式、上下文節點、命名空間解釋程序和返回的結果的類型,同時,在XPathResult中存放結果(通常為null)。
命名空間解釋程序,只有在XML代碼用到了XML命名空間時才是必要的,所以通常留空,置為null。返回結果的類型,可以是以下十個常量值之一:
- XPathResult.ANY_TYPE——返回符合XPath表達式類型的數據
- XPathResult.ANY_UNORDERED_NODE_TYPE——返回匹配節點的節點集合,但順序可能與文檔中的節點的順序不匹配
- XPathResult.BOOLEAN_TYPE——返回布爾值
- XPathResult.FIRST_ORDERED_NODE_TYPE——返回只包含一個節點的節點集合,且這個節點是在文檔中第一個匹配的節點
- XPathResult.NUMBER_TYPE——返回數字值
- XPathResult.ORDERED_NODE_ITERATOR_TYPE——返回匹配節點的節點集合,順序為節點在文檔中出現的順序。這是最常用到的結果類型
- XPathResult.ORDERED_NODE_SNAPSHOT_TYPE——返回節點集合快照,在文檔外捕獲節點,這樣將來對文檔的任何修改都不會影響這個節點列表。節點集合中的節點與它們出現在文檔中的順序一樣
- XPathResult.STRING_TYPE——返回字符串值
- XPathResult.UNORDERED_NODE_ITERATOR_TYPE——返回匹配節點的節點集合,不過順序可能不會按照節點在文檔中出現的順序排列
- XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE——返回節點集合快照,在文檔外捕獲節點,這樣將來對文檔的任何修改都不會影響這個節點列表。節點集合中的節點和文檔中原來的順序不一定一樣。
下面是使用ORDERED_NODE_ITERATOR_TYPE的例子:
var xmlDom = getXMLDOM();//我們之前寫的跨瀏覽器的XML DOM加載函數 loadXMLFile(xmlDom,"text.xml"); var evaluator = new XPathEvaluator(); var result =evaluator.evaluate("/root",xmlDom,null,XPathResult.ORDERED_NODE_ITERATOR_TYPE,null); var node; if (result) {//執行失敗會返回null while(node=result.iterateNext()) {//這個列表必須使用iterateNext方法遍歷 alert(node.tagName); } }