zoukankan      html  css  js  c++  java
  • javascript XPath 实现

    关于XPath的相关知识可以参看http://www.w3school.com.cn/xpath/index.asp

    在进行XPath之前要对xml文档进行加载。如何加载可参看上篇文章。

    1. var oXmlDom = XmlDom();  
    2. oXmlDom.load("exam1.xml");  

    针对IE,当在读取XML文档后,本身的对象提供了两个方法用于接收XPATH表达式。分别是:selectNodes及 selectSingleNode,这两个方法是作为oXmlDom.documentElement的方法调用的。相对Mozilla比较简单,当然功能是没有Mozilla实现XPATH的功能强大。

    1. oXmlDom.documentElement.selectNodes(xPath)    
    2. 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的属性。代码如下:

    1. /** 
    2.  * 查找匹配XPath表达式的节点(Mozilla实现selectNodes方法;IE自带该方法) 
    3.  *  
    4.  * @param sXPath 
    5.  *            XPAHT表达式 
    6.  * @return 节点集合数组 Array<Element> 
    7.  */  
    8. Element.prototype.selectNodes = function(sXPath) {  
    9.     var oEvaluator = new XPathEvaluator();  
    10.     var oResult = oEvaluator.evaluate(sXPath, thisnull,  
    11.             XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);  
    12.     var aNodes = new Array();  
    13.     if (oResult != null) {  
    14.         var oElement = oResult.iterateNext();  
    15.         while (oElement) {  
    16.             aNodes.push(oElement);  
    17.             oElement = oResult.iterateNext();  
    18.         }  
    19.     }  
    20.     return aNodes;  
    21. };  
    22. /** 
    23.  * 查找第一个匹配XPath表达式的节点(Mozilla实现selectSingleNode方法;IE自带该方法) 
    24.  *  
    25.  * @param sXPath 
    26.  *            XPAHT表达式 
    27.  * @return 节点元素对象 instanceof Element is true 
    28.  */  
    29. Element.prototype.selectSingleNode = function(sXPath) {  
    30.     var oEvaluator = new XPathEvaluator();  
    31.     var oResult = oEvaluator.evaluate(sXPath, thisnull,  
    32.             XPathResult.FIRST_ORDERED_NODE_TYPE, null);  
    33.     if (oResult != null) {  
    34.         return oResult.singleNodeValue;  
    35.     } else {  
    36.         return null;  
    37.     }  
    38. };  
    1. /** 
    2.  * 查找匹配XPath表达式的节点(Mozilla实现selectNodes方法;IE自带该方法) 
    3.  *  
    4.  * @param sXPath 
    5.  *            XPAHT表达式 
    6.  * @return 节点集合数组 Array<Element> 
    7.  */  
    8. Element.prototype.selectNodes = function(sXPath) {  
    9.     var oEvaluator = new XPathEvaluator();  
    10.     var oResult = oEvaluator.evaluate(sXPath, thisnull,  
    11.             XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);  
    12.     var aNodes = new Array();  
    13.     if (oResult != null) {  
    14.         var oElement = oResult.iterateNext();  
    15.         while (oElement) {  
    16.             aNodes.push(oElement);  
    17.             oElement = oResult.iterateNext();  
    18.         }  
    19.     }  
    20.     return aNodes;  
    21. };  
    22. /** 
    23.  * 查找第一个匹配XPath表达式的节点(Mozilla实现selectSingleNode方法;IE自带该方法) 
    24.  *  
    25.  * @param sXPath 
    26.  *            XPAHT表达式 
    27.  * @return 节点元素对象 instanceof Element is true 
    28.  */  
    29. Element.prototype.selectSingleNode = function(sXPath) {  
    30.     var oEvaluator = new XPathEvaluator();  
    31.     var oResult = oEvaluator.evaluate(sXPath, thisnull,  
    32.             XPathResult.FIRST_ORDERED_NODE_TYPE, null);  
    33.     if (oResult != null) {  
    34.         return oResult.singleNodeValue;  
    35.     } else {  
    36.         return null;  
    37.     }  
    38. };  
    /**
     * 查找匹配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的浏览器中使用:

    1. /** 
    2.  * 统计匹配指定模式的节点个数(该方法仅限于Mozilla) 
    3.  *  
    4.  * @param sXPath 
    5.  *            XPAHT表达式 
    6.  * @return 返回匹配节点个数。如没有匹配则返回0 
    7.  */  
    8. Element.prototype.count = function(sXPath) {  
    9.     var __count = 0;  
    10.     sXPath = "count(" + sXPath + ")";  
    11.     var oEvaluator = new XPathEvaluator();  
    12.     var oResult = oEvaluator.evaluate(sXPath, thisnull,  
    13.             XPathResult.NUMBER_TYPE, null);  
    14.     if (oResult) {  
    15.         __count = oResult.numberValue;  
    16.     }  
    17.     return __count;  
    18. };  
    19. /** 
    20.  * 判断指定XPath表达式是否有匹配节点(该方法仅限于Mozilla) 
    21.  *  
    22.  * @param sXPath 
    23.  *            XPAHT表达式 
    24.  * @return true|false 
    25.  */  
    26. Element.prototype.isMatch = function(sXPath) {  
    27.     var oEvaluator = new XPathEvaluator();  
    28.     var oResult = oEvaluator.evaluate(sXPath, thisnull,  
    29.             XPathResult.BOOLEAN_TYPE, null);  
    30.     return oResult.booleanValue;  
    31. };  
    1. /** 
    2.  * 统计匹配指定模式的节点个数(该方法仅限于Mozilla) 
    3.  *  
    4.  * @param sXPath 
    5.  *            XPAHT表达式 
    6.  * @return 返回匹配节点个数。如没有匹配则返回0 
    7.  */  
    8. Element.prototype.count = function(sXPath) {  
    9.     var __count = 0;  
    10.     sXPath = "count(" + sXPath + ")";  
    11.     var oEvaluator = new XPathEvaluator();  
    12.     var oResult = oEvaluator.evaluate(sXPath, thisnull,  
    13.             XPathResult.NUMBER_TYPE, null);  
    14.     if (oResult) {  
    15.         __count = oResult.numberValue;  
    16.     }  
    17.     return __count;  
    18. };  
    19. /** 
    20.  * 判断指定XPath表达式是否有匹配节点(该方法仅限于Mozilla) 
    21.  *  
    22.  * @param sXPath 
    23.  *            XPAHT表达式 
    24.  * @return true|false 
    25.  */  
    26. Element.prototype.isMatch = function(sXPath) {  
    27.     var oEvaluator = new XPathEvaluator();  
    28.     var oResult = oEvaluator.evaluate(sXPath, thisnull,  
    29.             XPathResult.BOOLEAN_TYPE, null);  
    30.     return oResult.booleanValue;  
    31. };  
    /**
     * 统计匹配指定模式的节点个数(该方法仅限于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语法的支持情况,为此做如下测试页面

    1. <?xml version="1.0" encoding="UTF-8" ?>  
    2. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  
    3. <html xmlns="http://www.w3.org/1999/xhtml">  
    4. <head>  
    5. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />  
    6. <mce:style type="text/css"><!--  
    7. #hea {  
    8.     border: 1px dotted orange;  
    9. }  
    10. #xml {  
    11.     float: left;  
    12.      400px;  
    13.     height: 600px;  
    14.     border: 1px dotted red;  
    15. }  
    16. #res {  
    17.     float: left;  
    18.     border: 1px solid green;  
    19.      500px;  
    20.     height: 600px;  
    21. }  
    22. --></mce:style><style type="text/css" mce_bogus="1">#hea {  
    23.     border: 1px dotted orange;  
    24. }  
    25. #xml {  
    26.     float: left;  
    27.      400px;  
    28.     height: 600px;  
    29.     border: 1px dotted red;  
    30. }  
    31. #res {  
    32.     float: left;  
    33.     border: 1px solid green;  
    34.      500px;  
    35.     height: 600px;  
    36. }</style>  
    37. <mce:script type="text/javascript" src="loadxml.js" mce_src="loadxml.js"></mce:script>  
    38. <title>Insert title here</title>  
    39. <mce:script type="text/javascript"><!--  
    40.       
    41.     function search(xPath) {  
    42.         var oXmlDom = XmlDom();  
    43.         oXmlDom.onreadystatechange = function() {  
    44.             //IE|FF  
    45.             if (oXmlDom.readyState == 4 || oXmlDom.readyState == "complete") {  
    46.             }  
    47.         }  
    48.         oXmlDom.load("exam1.xml");  
    49.         var aNodes = oXmlDom.documentElement.selectNodes(xPath);  
    50.         var sRes = "";  
    51.         for ( var index = 0; index < aNodes.length; index++) {  
    52.             sRes += aNodes[index].xml + "/r/n";  
    53.         }  
    54.         var oDiv = document.getElementById('res');  
    55.         oDiv.innerHTML = "";  
    56.         var xml = document.createTextNode(sRes);  
    57.         oDiv.appendChild(xml);  
    58.     }  
    59. // --></mce:script>  
    60. </head>  
    61. <body>  
    62. <div id="hea">  
    63. XPath表达式:<input type="text" name="sql" id="sql" size="60" /> <input  
    64.     type="button" value="search"  
    65.     onclick="search(document.getElementById('sql').value);" /></div>  
    66. <iframe src="exam1.xml" mce_src="exam1.xml" id="xml"></iframe>  
    67. <div id="res"></div>  
    68. </body>  
    69. </html>  
    1. <?xml version="1.0" encoding="UTF-8" ?>  
    2. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  
    3. <html xmlns="http://www.w3.org/1999/xhtml">  
    4. <head>  
    5. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />  
    6. <style type="text/css">  
    7. #hea {  
    8.     border: 1px dotted orange;  
    9. }  
    10.   
    11. #xml {  
    12.     float: left;  
    13.      400px;  
    14.     height: 600px;  
    15.     border: 1px dotted red;  
    16. }  
    17.   
    18. #res {  
    19.     float: left;  
    20.     border: 1px solid green;  
    21.      500px;  
    22.     height: 600px;  
    23. }  
    24. </style>  
    25. <script type="text/javascript" src="loadxml.js"></script>  
    26. <title>Insert title here</title>  
    27. <script type="text/javascript">  
    28.       
    29.     function search(xPath) {  
    30.         var oXmlDom = XmlDom();  
    31.         oXmlDom.onreadystatechange = function() {  
    32.             //IE|FF  
    33.             if (oXmlDom.readyState == 4 || oXmlDom.readyState == "complete") {  
    34.   
    35.             }  
    36.         }  
    37.         oXmlDom.load("exam1.xml");  
    38.         var aNodes = oXmlDom.documentElement.selectNodes(xPath);  
    39.         var sRes = "";  
    40.         for ( var index = 0; index < aNodes.length; index++) {  
    41.             sRes += aNodes[index].xml + "/r/n";  
    42.         }  
    43.         var oDiv = document.getElementById('res');  
    44.         oDiv.innerHTML = "";  
    45.         var xml = document.createTextNode(sRes);  
    46.         oDiv.appendChild(xml);  
    47.     }  
    48. </script>  
    49. </head>  
    50. <body>  
    51. <div id="hea">  
    52. XPath表达式:<input type="text" name="sql" id="sql" size="60" /> <input  
    53.     type="button" value="search"  
    54.     onclick="search(document.getElementById('sql').value);" /></div>  
    55. <iframe src="exam1.xml" id="xml"></iframe>  
    56. <div id="res"></div>  
    57. </body>  
    58. </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;
    	 400px;
    	height: 600px;
    	border: 1px dotted red;
    }
    
    #res {
    	float: left;
    	border: 1px solid green;
    	 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源文件如下:

    1. <?xml version="1.0" encoding="UTF-8"?>  
    2. <exam>  
    3.     <no id="1">  
    4.         <question1>我喜欢与历史学家交往<q>ceshi</q></question1>  
    5.         <question2>我做事进度较慢,但确保成效</question2>  
    6.         <value>4</value>  
    7.     </no>  
    8.     <no id="2">  
    9.         <question1>我想要每个人都喜欢我</question1>  
    10.         <question2>我一贯努力工作</question2>  
    11.         <value>7</value>  
    12.     </no>  
    13.     <no id="3">  
    14.         <question1>我力争第一</question1>  
    15.         <question2>我思考自身的长处</question2>  
    16.     </no>  
    17.     <no id="4">  
    18.         <question1>我思考有待改进之处</question1>  
    19.         <question2>我是一个偏重情感的人</question2>  
    20.     </no>  
    21.     <no id="5">  
    22.         <question1>我能够接受多种类型的人</question1>  
    23.         <question2>我想念我的朋友</question2>  
    24.     </no>  
    25.     <no id="6">  
    26.         <question1>与陌生人交谈使我兴奋</question1>  
    27.         <question2>我认为自己很能干</question2>  
    28.     </no>  
    29.     <no id="7">  
    30.         <question1>我通过与新人建立联系获得满足感</question1>  
    31.         <question2>竞争与挑战让我感到兴奋</question2>  
    32.     </no>  
    33.       
    34.     <no id="8">  
    35.         <question1>成为他人的知己使我满足</question1>  
    36.         <question2>我信守自己的价值观</question2>  
    37.     </no>  
    38. </exam>  
    1. <?xml version="1.0" encoding="UTF-8"?>  
    2. <exam>  
    3.     <no id="1">  
    4.         <question1>我喜欢与历史学家交往<q>ceshi</q></question1>  
    5.         <question2>我做事进度较慢,但确保成效</question2>  
    6.         <value>4</value>  
    7.     </no>  
    8.     <no id="2">  
    9.         <question1>我想要每个人都喜欢我</question1>  
    10.         <question2>我一贯努力工作</question2>  
    11.         <value>7</value>  
    12.     </no>  
    13.     <no id="3">  
    14.         <question1>我力争第一</question1>  
    15.         <question2>我思考自身的长处</question2>  
    16.     </no>  
    17.     <no id="4">  
    18.         <question1>我思考有待改进之处</question1>  
    19.         <question2>我是一个偏重情感的人</question2>  
    20.     </no>  
    21.     <no id="5">  
    22.         <question1>我能够接受多种类型的人</question1>  
    23.         <question2>我想念我的朋友</question2>  
    24.     </no>  
    25.     <no id="6">  
    26.         <question1>与陌生人交谈使我兴奋</question1>  
    27.         <question2>我认为自己很能干</question2>  
    28.     </no>  
    29.     <no id="7">  
    30.         <question1>我通过与新人建立联系获得满足感</question1>  
    31.         <question2>竞争与挑战让我感到兴奋</question2>  
    32.     </no>  
    33.     <no id="8">  
    34.         <question1>成为他人的知己使我满足</question1>  
    35.         <question2>我信守自己的价值观</question2>  
    36.     </no>  
    37. </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节点所包含的文本
    如果要下载测试文件可到http://leeyee.javaeye.com/blog/685352 进行下载
  • 相关阅读:
    两个layout之间怎么切换好
    测试- 就从这儿起步
    Fiddler 学习
    我的周记4——“要繁荣富强,不要再让人欺负了”
    谈谈游戏
    我的周记3——“雨打梨花深闭门,忘了青春,误了青春”
    我的周记2——“天道酬勤"
    说说Charles
    Book list
    STL学习笔记(仿函数)
  • 原文地址:https://www.cnblogs.com/amylis_chen/p/2710770.html
Copyright © 2011-2022 走看看