標籤:des 使用 os 檔案 資料 io
最近的開發中要用到htmlAgilityPackage, 所以記錄一下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//pbody/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 {選取rootroot {選取rootchild {空,因為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) {//執行失敗會返回nullwhile(node=result.iterateNext()) {//這個列表必須使用iterateNext方法遍曆alert(node.tagName);}}