關於XPath的相關知識可以參看http://www.w3school.com.cn/xpath/index.asp
在進行XPath之前要對xml文檔進行加載。如何加載可參看上篇文章。
- var oXmlDom = XmlDom();
- oXmlDom.load("exam1.xml");
針對IE,當在讀取XML文檔后,本身的對象提供了兩個方法用於接收XPATH表達式。分別是:selectNodes及 selectSingleNode,這兩個方法是作為oXmlDom.documentElement的方法調用的。相對Mozilla比較簡單,當然功能是沒有Mozilla實現XPATH的功能強大。
- oXmlDom.documentElement.selectNodes(xPath)
- oXmlDom.documentElement.selectSingleNode(xPath)
Mozilla實現XPATH的方式則相對比較復雜。需要創建XPathEvaluator對象,然后調用evaluate方法執行XPATH表達式。evaluate包含五個參數:XPath表達式、上下文節點、命名空間解釋程序及返回的結果類型,同時在XPathResult中存放結果(通常為 null)命名空間解釋程序通常留空。返回結果類型有:
XPathResult.ANY_TYPE——返回符合XPath表達式類型的數據;
XPathResult.ANY_UNORDERED_NODE_TYPE——返回匹配節點的節點集合,但順序可能與文檔中不同
XPathResult.BOOLEAN_TYPE——返回布爾值
XPathResult.FIRST_OREDERED_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——返回節點集合快照,但順序可能與文檔中不同
下面針對Mozilla實現selectNodes及selectSingleNode方法。由於oXmlDom.documentElement 為Elment對象,那么為了用相同的代碼兼容IE及Mozilla,可以將selectNodes及selectSingleNode作為 Element的屬性。代碼如下:
- /**
- * 查找匹配XPath表達式的節點(Mozilla實現selectNodes方法;IE自帶該方法)
- *
- * @param sXPath
- * XPAHT表達式
- * @return 節點集合數組 Array<Element>
- */
- Element.prototype.selectNodes = function(sXPath) {
- var oEvaluator = new XPathEvaluator();
- var oResult = oEvaluator.evaluate(sXPath, this, null,
- XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);
- var aNodes = new Array();
- if (oResult != null) {
- var oElement = oResult.iterateNext();
- while (oElement) {
- aNodes.push(oElement);
- oElement = oResult.iterateNext();
- }
- }
- return aNodes;
- };
- /**
- * 查找第一個匹配XPath表達式的節點(Mozilla實現selectSingleNode方法;IE自帶該方法)
- *
- * @param sXPath
- * XPAHT表達式
- * @return 節點元素對象 instanceof Element is true
- */
- Element.prototype.selectSingleNode = function(sXPath) {
- var oEvaluator = new XPathEvaluator();
- var oResult = oEvaluator.evaluate(sXPath, this, null,
- XPathResult.FIRST_ORDERED_NODE_TYPE, null);
- if (oResult != null) {
- return oResult.singleNodeValue;
- } else {
- return null;
- }
- };
- /**
- * 查找匹配XPath表達式的節點(Mozilla實現selectNodes方法;IE自帶該方法)
- *
- * @param sXPath
- * XPAHT表達式
- * @return 節點集合數組 Array<Element>
- */
- Element.prototype.selectNodes = function(sXPath) {
- var oEvaluator = new XPathEvaluator();
- var oResult = oEvaluator.evaluate(sXPath, this, null,
- XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);
- var aNodes = new Array();
- if (oResult != null) {
- var oElement = oResult.iterateNext();
- while (oElement) {
- aNodes.push(oElement);
- oElement = oResult.iterateNext();
- }
- }
- return aNodes;
- };
- /**
- * 查找第一個匹配XPath表達式的節點(Mozilla實現selectSingleNode方法;IE自帶該方法)
- *
- * @param sXPath
- * XPAHT表達式
- * @return 節點元素對象 instanceof Element is true
- */
- Element.prototype.selectSingleNode = function(sXPath) {
- var oEvaluator = new XPathEvaluator();
- var oResult = oEvaluator.evaluate(sXPath, this, null,
- XPathResult.FIRST_ORDERED_NODE_TYPE, null);
- if (oResult != null) {
- return oResult.singleNodeValue;
- } else {
- return null;
- }
- };
/**
* 查找匹配XPath表達式的節點(Mozilla實現selectNodes方法;IE自帶該方法)
*
* @param sXPath
* XPAHT表達式
* @return 節點集合數組 Array<Element>
*/
Element.prototype.selectNodes = function(sXPath) {
var oEvaluator = new XPathEvaluator();
var oResult = oEvaluator.evaluate(sXPath, this, null,
XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);
var aNodes = new Array();
if (oResult != null) {
var oElement = oResult.iterateNext();
while (oElement) {
aNodes.push(oElement);
oElement = oResult.iterateNext();
}
}
return aNodes;
};
/**
* 查找第一個匹配XPath表達式的節點(Mozilla實現selectSingleNode方法;IE自帶該方法)
*
* @param sXPath
* XPAHT表達式
* @return 節點元素對象 instanceof Element is true
*/
Element.prototype.selectSingleNode = function(sXPath) {
var oEvaluator = new XPathEvaluator();
var oResult = oEvaluator.evaluate(sXPath, this, null,
XPathResult.FIRST_ORDERED_NODE_TYPE, null);
if (oResult != null) {
return oResult.singleNodeValue;
} else {
return null;
}
};
這樣我們就完成了Mozilla對XPath的實現。
當然Mozilla本身實現的XPath的操作要比單純的IE提供的selectNodes及selectSingleNode方法更強大,而且對與XPath表達式的支持也更好。我們可以再擴充一些方法,但注意了,下面這些方法只能在支持Mozilla的瀏覽器中使用:
- /**
- * 統計匹配指定模式的節點個數(該方法僅限於Mozilla)
- *
- * @param sXPath
- * XPAHT表達式
- * @return 返回匹配節點個數。如沒有匹配則返回0
- */
- Element.prototype.count = function(sXPath) {
- var __count = 0;
- sXPath = "count(" + sXPath + ")";
- var oEvaluator = new XPathEvaluator();
- var oResult = oEvaluator.evaluate(sXPath, this, null,
- XPathResult.NUMBER_TYPE, null);
- if (oResult) {
- __count = oResult.numberValue;
- }
- return __count;
- };
- /**
- * 判斷指定XPath表達式是否有匹配節點(該方法僅限於Mozilla)
- *
- * @param sXPath
- * XPAHT表達式
- * @return true|false
- */
- Element.prototype.isMatch = function(sXPath) {
- var oEvaluator = new XPathEvaluator();
- var oResult = oEvaluator.evaluate(sXPath, this, null,
- XPathResult.BOOLEAN_TYPE, null);
- return oResult.booleanValue;
- };
- /**
- * 統計匹配指定模式的節點個數(該方法僅限於Mozilla)
- *
- * @param sXPath
- * XPAHT表達式
- * @return 返回匹配節點個數。如沒有匹配則返回0
- */
- Element.prototype.count = function(sXPath) {
- var __count = 0;
- sXPath = "count(" + sXPath + ")";
- var oEvaluator = new XPathEvaluator();
- var oResult = oEvaluator.evaluate(sXPath, this, null,
- XPathResult.NUMBER_TYPE, null);
- if (oResult) {
- __count = oResult.numberValue;
- }
- return __count;
- };
- /**
- * 判斷指定XPath表達式是否有匹配節點(該方法僅限於Mozilla)
- *
- * @param sXPath
- * XPAHT表達式
- * @return true|false
- */
- Element.prototype.isMatch = function(sXPath) {
- var oEvaluator = new XPathEvaluator();
- var oResult = oEvaluator.evaluate(sXPath, this, null,
- XPathResult.BOOLEAN_TYPE, null);
- return oResult.booleanValue;
- };
/**
* 統計匹配指定模式的節點個數(該方法僅限於Mozilla)
*
* @param sXPath
* XPAHT表達式
* @return 返回匹配節點個數。如沒有匹配則返回0
*/
Element.prototype.count = function(sXPath) {
var __count = 0;
sXPath = "count(" + sXPath + ")";
var oEvaluator = new XPathEvaluator();
var oResult = oEvaluator.evaluate(sXPath, this, null,
XPathResult.NUMBER_TYPE, null);
if (oResult) {
__count = oResult.numberValue;
}
return __count;
};
/**
* 判斷指定XPath表達式是否有匹配節點(該方法僅限於Mozilla)
*
* @param sXPath
* XPAHT表達式
* @return true|false
*/
Element.prototype.isMatch = function(sXPath) {
var oEvaluator = new XPathEvaluator();
var oResult = oEvaluator.evaluate(sXPath, this, null,
XPathResult.BOOLEAN_TYPE, null);
return oResult.booleanValue;
};
當然上述方法,如果是在IE中,可以同過IE提供最基本的兩個方法解決,這里就不多做贅述。
下面我們最完成的代碼做下測試,看下上述編碼對與XPath語法的支持情況,為此做如下測試頁面
- <?xml version="1.0" encoding="UTF-8" ?>
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
- <html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
- <mce:style type="text/css"><!--
- #hea {
- border: 1px dotted orange;
- }
- #xml {
- float: left;
- width: 400px;
- height: 600px;
- border: 1px dotted red;
- }
- #res {
- float: left;
- border: 1px solid green;
- width: 500px;
- height: 600px;
- }
- --></mce:style><style type="text/css" mce_bogus="1">#hea {
- border: 1px dotted orange;
- }
- #xml {
- float: left;
- width: 400px;
- height: 600px;
- border: 1px dotted red;
- }
- #res {
- float: left;
- border: 1px solid green;
- width: 500px;
- height: 600px;
- }</style>
- <mce:script type="text/javascript" src="loadxml.js" mce_src="loadxml.js"></mce:script>
- <title>Insert title here</title>
- <mce:script type="text/javascript"><!--
- function search(xPath) {
- var oXmlDom = XmlDom();
- oXmlDom.onreadystatechange = function() {
- //IE|FF
- if (oXmlDom.readyState == 4 || oXmlDom.readyState == "complete") {
- }
- }
- oXmlDom.load("exam1.xml");
- var aNodes = oXmlDom.documentElement.selectNodes(xPath);
- var sRes = "";
- for ( var index = 0; index < aNodes.length; index++) {
- sRes += aNodes[index].xml + "/r/n";
- }
- var oDiv = document.getElementById('res');
- oDiv.innerHTML = "";
- var xml = document.createTextNode(sRes);
- oDiv.appendChild(xml);
- }
- // --></mce:script>
- </head>
- <body>
- <div id="hea">
- XPath表達式:<input type="text" name="sql" id="sql" size="60" /> <input
- type="button" value="search"
- onclick="search(document.getElementById('sql').value);" /></div>
- <iframe src="exam1.xml" mce_src="exam1.xml" id="xml"></iframe>
- <div id="res"></div>
- </body>
- </html>
- <?xml version="1.0" encoding="UTF-8" ?>
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
- <html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
- <style type="text/css">
- #hea {
- border: 1px dotted orange;
- }
- #xml {
- float: left;
- width: 400px;
- height: 600px;
- border: 1px dotted red;
- }
- #res {
- float: left;
- border: 1px solid green;
- width: 500px;
- height: 600px;
- }
- </style>
- <script type="text/javascript" src="loadxml.js"></script>
- <title>Insert title here</title>
- <script type="text/javascript">
- function search(xPath) {
- var oXmlDom = XmlDom();
- oXmlDom.onreadystatechange = function() {
- //IE|FF
- if (oXmlDom.readyState == 4 || oXmlDom.readyState == "complete") {
- }
- }
- oXmlDom.load("exam1.xml");
- var aNodes = oXmlDom.documentElement.selectNodes(xPath);
- var sRes = "";
- for ( var index = 0; index < aNodes.length; index++) {
- sRes += aNodes[index].xml + "/r/n";
- }
- var oDiv = document.getElementById('res');
- oDiv.innerHTML = "";
- var xml = document.createTextNode(sRes);
- oDiv.appendChild(xml);
- }
- </script>
- </head>
- <body>
- <div id="hea">
- XPath表達式:<input type="text" name="sql" id="sql" size="60" /> <input
- type="button" value="search"
- onclick="search(document.getElementById('sql').value);" /></div>
- <iframe src="exam1.xml" id="xml"></iframe>
- <div id="res"></div>
- </body>
- </html>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<style type="text/css">
#hea {
border: 1px dotted orange;
}
#xml {
float: left;
width: 400px;
height: 600px;
border: 1px dotted red;
}
#res {
float: left;
border: 1px solid green;
width: 500px;
height: 600px;
}
</style>
<script type="text/javascript" src="loadxml.js"></script>
<title>Insert title here</title>
<script type="text/javascript">
function search(xPath) {
var oXmlDom = XmlDom();
oXmlDom.onreadystatechange = function() {
//IE|FF
if (oXmlDom.readyState == 4 || oXmlDom.readyState == "complete") {
}
}
oXmlDom.load("exam1.xml");
var aNodes = oXmlDom.documentElement.selectNodes(xPath);
var sRes = "";
for ( var index = 0; index < aNodes.length; index++) {
sRes += aNodes[index].xml + "/r/n";
}
var oDiv = document.getElementById('res');
oDiv.innerHTML = "";
var xml = document.createTextNode(sRes);
oDiv.appendChild(xml);
}
</script>
</head>
<body>
<div id="hea">
XPath表達式:<input type="text" name="sql" id="sql" size="60" /> <input
type="button" value="search"
onclick="search(document.getElementById('sql').value);" /></div>
<iframe src="exam1.xml" id="xml"></iframe>
<div id="res"></div>
</body>
</html>
exam1.xml源文件如下:
- <?xml version="1.0" encoding="UTF-8"?>
- <exam>
- <no id="1">
- <question1>我喜歡與歷史學家交往<q>ceshi</q></question1>
- <question2>我做事進度較慢,但確保成效</question2>
- <value>4</value>
- </no>
- <no id="2">
- <question1>我想要每個人都喜歡我</question1>
- <question2>我一貫努力工作</question2>
- <value>7</value>
- </no>
- <no id="3">
- <question1>我力爭第一</question1>
- <question2>我思考自身的長處</question2>
- </no>
- <no id="4">
- <question1>我思考有待改進之處</question1>
- <question2>我是一個偏重情感的人</question2>
- </no>
- <no id="5">
- <question1>我能夠接受多種類型的人</question1>
- <question2>我想念我的朋友</question2>
- </no>
- <no id="6">
- <question1>與陌生人交談使我興奮</question1>
- <question2>我認為自己很能干</question2>
- </no>
- <no id="7">
- <question1>我通過與新人建立聯系獲得滿足感</question1>
- <question2>競爭與挑戰讓我感到興奮</question2>
- </no>
- <no id="8">
- <question1>成為他人的知己使我滿足</question1>
- <question2>我信守自己的價值觀</question2>
- </no>
- </exam>
- <?xml version="1.0" encoding="UTF-8"?>
- <exam>
- <no id="1">
- <question1>我喜歡與歷史學家交往<q>ceshi</q></question1>
- <question2>我做事進度較慢,但確保成效</question2>
- <value>4</value>
- </no>
- <no id="2">
- <question1>我想要每個人都喜歡我</question1>
- <question2>我一貫努力工作</question2>
- <value>7</value>
- </no>
- <no id="3">
- <question1>我力爭第一</question1>
- <question2>我思考自身的長處</question2>
- </no>
- <no id="4">
- <question1>我思考有待改進之處</question1>
- <question2>我是一個偏重情感的人</question2>
- </no>
- <no id="5">
- <question1>我能夠接受多種類型的人</question1>
- <question2>我想念我的朋友</question2>
- </no>
- <no id="6">
- <question1>與陌生人交談使我興奮</question1>
- <question2>我認為自己很能干</question2>
- </no>
- <no id="7">
- <question1>我通過與新人建立聯系獲得滿足感</question1>
- <question2>競爭與挑戰讓我感到興奮</question2>
- </no>
- <no id="8">
- <question1>成為他人的知己使我滿足</question1>
- <question2>我信守自己的價值觀</question2>
- </no>
- </exam>
<?xml version="1.0" encoding="UTF-8"?> <exam> <no id="1"> <question1>我喜歡與歷史學家交往<q>ceshi</q></question1> <question2>我做事進度較慢,但確保成效</question2> <value>4</value> </no> <no id="2"> <question1>我想要每個人都喜歡我</question1> <question2>我一貫努力工作</question2> <value>7</value> </no> <no id="3"> <question1>我力爭第一</question1> <question2>我思考自身的長處</question2> </no> <no id="4"> <question1>我思考有待改進之處</question1> <question2>我是一個偏重情感的人</question2> </no> <no id="5"> <question1>我能夠接受多種類型的人</question1> <question2>我想念我的朋友</question2> </no> <no id="6"> <question1>與陌生人交談使我興奮</question1> <question2>我認為自己很能干</question2> </no> <no id="7"> <question1>我通過與新人建立聯系獲得滿足感</question1> <question2>競爭與挑戰讓我感到興奮</question2> </no> <no id="8"> <question1>成為他人的知己使我滿足</question1> <question2>我信守自己的價值觀</question2> </no> </exam>
我們可以在輸入框中進行測試。使用XPath語法 進行測試,當然大部分語法都可以在FF中測試通過,但在IE中,顯然對Xpath軸 是不支持的,同時對XPath謂語表達式中的last()、position()也是不支持的。
以下是一些測試語法,大家可以試下:
//IE /FF 均測試通過
//no 或者 /exam/no 選取所有no節點
//no[@id='1'] 選取no節點屬性為1的節點
//no/* 選取no的所有子節點
//no[@*] 選取所有帶有屬性的no節點
//no[value>4] 選取no節點下value節點值大於4的no節點
//no/question1/q | //no[@id='2'] 選取no下question1中的q節點或着no節點屬性為1的節點
//no/question1/text() 取no節點下所有的question1節點所包含的文本
//IE不支持XPath軸表達式
//ff
//no[last()-1] 選取倒數第一個no節點
//no[position()<3] 選擇位置小於3的no節點
child::no 選取當前文檔所有的no節點
//no/child::question1 選取no節點下所有的question1節點
//no/child::question1/child::text() 取no節點下所有的question1節點所包含的文本
