javascript快速入門26--XPath

水之原發表於2013-12-04

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);
        }
    }

 

相關文章