Xpath現在很少被我們使用,因為JSON現在很盛行。可是在XML做為數據交換格式的年代,Xpath在我們隨機訪問大的xml文檔結構的時候扮演著非常重要的位置。也許大家現在很多沒有注意到,DOM Level 3 XPath指定的接口已經被Firefox,Safari, Chrome, and Opera實現了。他們所實現的核心接口就是XPathEvaluator,它包含一些能夠使用xpath表達式進行工作的方法,最主要的方法就是evaluate(),它能夠接受五個參數1.xpath查詢字符串2.指明xpath查詢字符串應該從哪個節點開始3.命名空間解析器(稍後介紹)4.返回的結果類型5.返回的結果應該添加到那個對象上(很少被使用,因為結果主要通過evaluate()返回)。
主要有10中不同的返回類型。每一種就代表XPathResult對象的一個常量。
介紹了這麼多,那麼我們該如何使用這些api進行操作呢?
evaluate()函數返回的信息完全依賴於請求的結果類型。
為了執行xpath查詢,需要使用XPathEvaluator對象,你可以生成一個新的對象也可以使用內置的對象,如果生成一個新的對象就要初始化XPathEvaluator。
var evaluator = new XPathEvaluator();
//得到第一個div
var result = evaluator.evaluate("//div", document.documentElement, null,
XPathResult.FIRST_ORDERED_NODE_TYPE, null);
alert("First div ID is " + result.singleNodeValue.id);
在Firefox, Safari, Chrome, and Opera,所有的文檔實例都實現了XPathEvaluator接口,這樣的話如果在HTML頁面中執行的查詢的話,我們可以使用document.evaluate(),如果通過XMLHttpRequest或者其他機制得到XML文檔,evaluate()方法也可以使用,例如:
//get first div
var result = document.evaluate("//div", document.documentElement, null,
XPathResult.FIRST_ORDERED_NODE_TYPE, null);
alert("First div ID is " + result.singleNodeValue.id);
下面介紹兩種返回多節點的方式,還是先看看實例:
//get all divs - iterator style
var result = document.evaluate("//div", document.documentElement, null,
XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);
if (result){
var node = result.iterateNext();
while(node) {
alert(node.id);
node = node.iterateNext();
}
}
//get all divs - SNAPSHOT style
var result = document.evaluate("//div", document.documentElement, null,
XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
if (result){
for (var i=0, len=result.snapshotLength; i < len; i++) {
alert(result.snapshotItem(i).id);
}
}
命名空間
如果你只是使用xpath在html文檔中簡單的查詢,evaluate()中的命名空間解析器參數一般為null,如果你傾向於使用xpath在包含命名空間的xml文檔中查詢,那麼你應該學會怎樣創建和使用命名空間解析器。
除了默認的命名空間以外,每個命名空間URI都映射到一個指定的前綴。每一個命名空間解析器是為xpath引擎在命名空間前綴和命名空間uri之間進行映射。有兩種生成命名空間解析器的方法,第一種如下:創建一個接受命名空間前綴作為參數的方法,然後返回對應的url ,如下:
function resolver(prefix){
switch(prefix){
case "wrox": return "http://www.wrox.com/";
case "ncz": return "http://www.nczonline.net/";
default: return "http://www.yahoo.com/";
}
}
第二種使用一個包含命名空間信息的節點,來生成一個命名空間解析器。
<books xmlns:wrox="http://www.wrox.com/" xmlns="http://www.amazon.com/"> <wrox:book>Professional JavaScript</book> </books>
<books>元素包含了所有的命名空間信息,你可以把這個節點的引用傳給XPathEvaluator對象的createNSResovler()方法,然後可以自動的得到一個命名空間解析器。
如:
var evaluator = new XPathEvaluator(); var resolver = evaluator.createNSResolver(xmldoc.documentElement);
使用上面的任意一個方法可以很容易的在含有命名空間xml文檔中進行查詢。
var evaluator = new XPathEvaluator();
var resolver = evaluator.createNSResolver(xmldoc.documentElement);
var result = evaluator.evaluate("wrox:book", xmldoc.documentElement,
resolver, XPathResult.FIRST_ORDERED_NODE_TYPE, null);
if (result){
alert(result.singleNodeValue.firstChild.nodeValue);
}
注意:如果你在含有命名空間的xml文當中執行查詢,不提供命名空間解析器,就會發生錯誤。
IE浏覽器中對xpath的支持
IE8還沒有實現DOM Level 3 XPath中定義的接口,但是它對xpath也有一定的支持,IE中的xpath功能主要對xml文檔可用,對document的對象不可用。
在IE中生成xml文檔的方法:
function createDocument(){
if (typeof arguments.callee.activeXString != "string"){
var versions = ["MSXML2.DOMDocument.6.0",
"MSXML2.DOMDocument.3.0",
"MSXML2.DOMDocument"];
for (var i=0,len=versions.length; i < len; i++){
try {
var xmldom = new ActiveXObject(versions[i]);
arguments.callee.activeXString = versions[i];
return xmldom;
} catch (ex){
//skip
}
}
}
return new ActiveXObject(arguments.callee.activeXString);
}
生成文檔對象以後,可以使用loadXML()方法加載內容:
var xmldoc = createDocument();
xmldoc.loadXML("");
第二種方法通過XMLHttRequest對象進行請求生成xml對象。
var xhr = new XMLHttpRequest(),
xmldoc;
xhr.open("get", "data.xml", true);
xhr.onreadystatechange = function(){
if (xhr.readyState == 4){
if (xhr.status >= 200 && xhr.status < 300){
xmldoc = xhr.responseXML;
}
};
xhr.send(null);
第三種方法是使用<xml>標簽,Microsoft把這種方法叫做xml數據島,如下:
<xml id="myXML" src="data.xml"></xml>
然後:
var xmldoc = document.getElementById("myXML").XMLDocument;
XPath支持:
在ie中的xml文檔對象對xpath進行支持有兩個內置方法:
selectSingleNode() and selectNodes(),每個方法都接受xpath表達式作為參數,然後分別放回第一個匹配的節點和所有匹配的節點。
命名空間支持:
對於
<books xmlns:wrox="http://www.wrox.com/" xmlns="http://www.amazon.com/"> <wrox:book>Professional JavaScript</book>
</books>這段xml文檔,我們應該使用下面的方法進行查詢,即首先使用setProperty(),來設置xml文檔的命名空間。
xmldoc.setProperty("SelectionNamespaces",
"xmlns:wrox='http://www.wrox.com/' xmlns='http://www.amazon.com/'");
var book = xmldoc.documentElement.selectSingleNode("wrox:book");