javascript XPath 实现

关于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.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.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;
};

当然上述方法,如果是在IE中,可以同过IE提供最基本的两个方法解决,这里就不多做赘述。

下面我们最完成的代码做下测试,看下上述编码对与XPath语法的支持情况,为此做如下测试页面








Insert title here



XPath表达式:








Insert title here



XPath表达式:

exam1.xml源文件如下:



	
		我喜欢与历史学家交往ceshi
		我做事进度较慢,但确保成效
		4
	
	
		我想要每个人都喜欢我
		我一贯努力工作
		7
	
	
		我力争第一
		我思考自身的长处
	
	
		我思考有待改进之处
		我是一个偏重情感的人
	
	
		我能够接受多种类型的人
		我想念我的朋友
	
	
		与陌生人交谈使我兴奋
		我认为自己很能干
	
	
		我通过与新人建立联系获得满足感
		竞争与挑战让我感到兴奋
	
	
	
		成为他人的知己使我满足
		我信守自己的价值观
	



	
		我喜欢与历史学家交往ceshi
		我做事进度较慢,但确保成效
		4
	
	
		我想要每个人都喜欢我
		我一贯努力工作
		7
	
	
		我力争第一
		我思考自身的长处
	
	
		我思考有待改进之处
		我是一个偏重情感的人
	
	
		我能够接受多种类型的人
		我想念我的朋友
	
	
		与陌生人交谈使我兴奋
		我认为自己很能干
	
	
		我通过与新人建立联系获得满足感
		竞争与挑战让我感到兴奋
	
	
		成为他人的知己使我满足
		我信守自己的价值观
	

我们可以在输入框中进行测试。使用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 进行下载

转载于:https://my.oschina.net/yeelee/blog/650911

你可能感兴趣的:(javascript XPath 实现)