1. 程式人生 > >二十七、XPath

二十七、XPath

tor 元素 mat snapshot 文檔 bool 兩個 結果 做出

二十七、XPath

XPath是一種節點查找手段,對比之前使用標準DOM去查找XML中的節點方式,大大降低了查找難度,方便開發者使用。但是,DOM3級以前的標準並沒有就XPath做出規範;直到DOM3在首次推薦到標準規範行列。大部分瀏覽器實現了這個標準,IE則以自己的方式實現了XPath。

1.IE中的XPath

在IE8及之前的瀏覽器,XPath是采用內置基於ActiveX的XML DOM文檔對象實現的。在每一個節點上提供了兩個方法:selectSingleNode()和selectNodes()。

selectSingleNode()方法接受一個XPath模式(也就是查找路徑),找到匹配的第一個節點並將它返回,沒有則返回null。

var user = xmlDom.selectSingleNode(‘root/user‘); //得到第一個user節點

alert(user.xml); //查看xml序列

alert(user.tagName); //節點元素名

alert(user.firstChild.nodeValue); //節點內的值

上下文節點:

我們通過xmlDom這個對象實例調用方法,而xmlDom這個對象實例其實就是一個上下文節點,這個節點指針指向的是根,也就是root元素之前。那麽如果我們把這個指針指向user元素之前,那麽結果就會有所變化。

//通過xmlDom,並且使用root/user的路徑

var user = xmlDom.selectSingleNode(‘root/user‘);

alert(user.tagName); //user

//通過xmlDom.documentElement,並且使用user路徑,省去了root

var user = xmlDom.documentElement.selectSingleNode(‘user‘);

alert(user.tagName); //user

//通過xmlDom,並且使用user路徑,省去了root

var user = xmlDom.selectSingleNode(‘user‘);

alert(user.tagName); //找不到了,出錯

PS:xmlDom和xmlDom.documentElement都是上下文節點,主要就是定位當前路徑查找的指針,而xmlDom對象實例的指針就是在最根上。

XPath常用語法

//通過user[n]來獲取第n+1條節點,PS:XPath其實是按1為起始值的

var user = xmlDom.selectSingleNode(‘root/user[1]‘);

alert(user.xml);

//通過text()獲取節點內的值

var user = xmlDom.selectSingleNode(‘root/user/text()‘);

alert(user.xml);

alert(user.nodeValue);

//通過//user表示在整個xml獲取到user節點,不關心任何層次

var user = xmlDom.selectSingleNode(‘//user‘);

alert(user.xml);

//通過root//user表示在root包含的層次下獲取到user節點,在root內不關心任何層次

var user = xmlDom.selectSingleNode(‘root//user‘);

alert(user.tagName);

//通過root/user[@id=6]表示獲取user中id=6的節點

var user = xmlDom.selectSingleNode(‘root/user[@id=6]‘);

alert(user.xml);

PS:更多的XPath語法,可以參考XPath手冊或者XML DOM手冊進行參考,這裏只提供了最常用的語法。

selectSingleNode()方法是獲取單一節點,而selectNodes()方法則是獲取一個節點集合。

var users = xmlDom.selectNodes(‘root/user‘); //獲取user節點集合

alert(users.length);

alert(users[1].xml);

2.W3C下的XPath

在DOM3級XPath規範定義的類型中,最重要的兩個類型是XPathEvaluator和XPathResult。其中,XPathEvaluator用於在特定上下文對XPath表達式求值。


XPathEvaluator的方法

方法

說明

createExpression(e, n)

將XPath表達式及命名空間轉化成XPathExpression

createNSResolver(n)

根據n命名空間創建一個新的XPathNSResolver對象

evaluate(e, c, n ,t ,r)

結合上下文來獲取XPath表達式的值

W3C實現XPath查詢節點比IE來的復雜,首先第一步就是需要得到XPathResult對象的實例。得到這個對象實例有兩種方法,一種是通過創建XPathEvaluator對象執行evaluate()方法,另一種是直接通過上下文節點對象(比如xmlDom)來執行evaluate()方法。

//使用XPathEvaluator對象創建XPathResult

var eva = new XPathEvaluator();

var result = eva.evaluate(‘root/user‘, xmlDom, null,

XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);

alert(result);

//使用上下文節點對象(xmlDom)創建XPathResult

var result = xmlDom.evaluate(‘root/user‘, xmlDom, null,

XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);

alert(result);

相對而言,第二種簡單方便一點,但evaluate方法有五個屬性:1.XPath路徑、2.上下文節點對象、3.命名空間求解器(通常是null)、4.返回結果類型、5保存結果的XPathResult對象(通常是null)。

對於返回的結果類型,有10中不同的類型

常量

說明

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

返回節點集合快照,在文檔外捕獲節點,這樣將來對文檔的任何修改都不會影響這個節點列表

PS:上面的常量過於繁重,對於我們只需要學習了解,其實也就需要兩個:1.獲取一個單一節、2.獲取一個節點集合。

1.獲取一個單一節點

var result = xmlDom.evaluate(‘root/user‘, xmlDom, null,

XPathResult.FIRST_ORDERED_NODE_TYPE, null);

if (result !== null) {

alert(result.singleNodeValue.tagName); //singleNodeValue屬性得到節點對象

}

2.獲取節點集合

var result = xmlDom.evaluate(‘root/user‘, xmlDom, null,

XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);

var nodes = [];

if (result !== null) {

while ((node = result.iterateNext()) !== null) {

nodes.push(node);

}

}

PS:節點集合的獲取方式,是通過叠代器遍歷而來的,我們保存到數據中就模擬出IE相似的風格。

3.XPath跨瀏覽器兼容

如果要做W3C和IE的跨瀏覽器兼容,我們要思考幾個問題:1.如果傳遞一個節點的下標,IE是從0開始計算,W3C從1開始計算,可以通過傳遞獲取下標進行增1減1的操作來進行。2.獨有的功能放棄,為了保證跨瀏覽器。3.只獲取單一節點和節點列表即可,基本可以完成所有的操作。

//跨瀏覽器獲取單一節點

function selectSingleNode(xmlDom, xpath) {

var node = null;

if (typeof xmlDom.evaluate != ‘undefined‘) {

var patten = /\[(\d+)\]/g;

var flag = xpath.match(patten);

var num = 0;

if (flag !== null) {

num = parseInt(RegExp.$1) + 1;

xpath = xpath.replace(patten, ‘[‘ + num + ‘]‘);

}

var result = xmlDom.evaluate(xpath, xmlDom, null,

XPathResult.FIRST_ORDERED_NODE_TYPE, null);

if (result !== null) {

node = result.singleNodeValue;

}

} else if (typeof xmlDom.selectSingleNode != ‘undefined‘) {

node = xmlDom.selectSingleNode(xpath);

}

return node;

}

//跨瀏覽器獲取節點集合

function selectNodes(xmlDom, xpath) {

var nodes = [];

if (typeof xmlDom.evaluate != ‘undefined‘) {

var patten = /\[(\d+)\]/g;

var flag = xpath.match(patten);

var num = 0;

if (flag !== null) {

num = parseInt(RegExp.$1) + 1;

xpath = xpath.replace(patten, ‘[‘ + num + ‘]‘);

}

var node = null;

   var result = xmlDom.evaluate(‘root/user‘, xmlDom, null,

XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);

   if (result !== null) {

   while ((node = result.iterateNext()) !== null) {

   nodes.push(node);

   }

   }

} else if (typeof xmlDom.selectNodes != ‘undefined‘) {

nodes = xmlDom.selectNodes(xpath);

}

return nodes;

}

PS:在傳遞xpath路徑時,沒有做驗證判斷是否合法,有興趣的同學可以自行完成。在XML還有一個重要章節是XSLT和EX4,由於在使用頻率的緣故,我們暫且擱置。

二十七、XPath