第一百二十六节,JavaScript,XPath操做xml节点node
学习要点:数组
1.IE中的XPath浏览器
2.W3C中的XPathdom
3.XPath跨浏览器兼容函数
XPath是一种节点查找手段,对比以前使用标准DOM去查找XML中的节点方式,大大下降了查找难度,方便开发者使用。可是,DOM3级之前的标准并无就XPath作出规范;直到DOM3在首次推荐到标准规范行列。大部分浏览器实现了这个标准,IE则以本身的方式实现了XPath。学习
一.IE中的XPathlua
在IE8及以前的浏览器,XPath是采用内置基于ActiveX的XML DOM文档对象实现的。在每个节点上提供了两个方法:selectSingleNode()和selectNodes()。spa
selectSingleNode()方法接受一个XPath模式(也就是查找路径),找到匹配的第一个节点并将它返回,没有则返回null。指针
selectSingleNode()方法,查找xml节点,查找单一节点若是有相同的节点只返回第一个节点,有参参数是要查找的节点路径,此方法只支持IE而且是IE9如下
使用方式
XML DOM对象.selectSingleNode('要查找的节点路径')code
var xml = '<root><user id="5">Lee</user><user id="6">Koko</user></root>'; //定义xml字符串 var xmldom = getXMLDOM(xml); //建立XML DOM对象,接收xml字符串 //经过XML DOM对象查找xml标签节点 var chzhao = xmldom.selectSingleNode('root/user'); //selectSingleNode()方法,查找xml节点,有参参数是要查找的节点路径,此方法只支持IE而且是IE9如下 alert(serializeXML(chzhao)); //执行序列化函数,序列化查找到的节点 alert(chzhao.tagName); //打印查找到的元素标签名称 alert(chzhao.firstChild.nodeValue); //打印查找到的元素文本内容 //首先,咱们须要跨浏览器获取XML DOM function getXMLDOM(xmlStr) { //自定义跨浏览器建立xml DOM对象,接收一个参数xml字符串 var xmlDom = null; //初始化一个对象 if (typeof window.DOMParser != 'undefined') { //判断DOMParser类型不等于undefined说明支持 //建立DOMParser对象,而且建立xml DOM对象 xmlDom = (new DOMParser()).parseFromString(xmlStr, 'text/xml'); //获取错误信息的parsererror标签 var errors = xmlDom.getElementsByTagName('parsererror'); //判断错误信息标签返回集合长度大于0,说明xml有错误 if (errors.length > 0) { //建立一个错误对象,获取到第一个错误标签,而且获取到他的文本内容 throw new Error('XML解析错误:' + errors[0].firstChild.nodeValue); } //若是不支持DOMParser类型,尝试IE的方法 } else if (typeof window.ActiveXObject != 'undefined') { //判断ActiveXObject类型不等于undefined说明支持 var version = [ //建立一个数组,元素分别为3个xml版本 'MSXML2.DOMDocument.6.0', 'MSXML2.DOMDocument.3.0', 'MSXML2.DOMDocument' ]; for (var i = 0; i < version.length; i++) { //根据数组的长度循环次数 try { //尝试着执行每次循环到的xml版本,建立xml对象 xmlDom = new ActiveXObject(version[i]); } catch (e) { //若是出错跳过执行第二次循环 //跳过 } } xmlDom.loadXML(xmlStr); //载入xml字符串 if (xmlDom.parseError != 0) { //判断载入xml错误返回代码,若是不等于0说明xml有错 //建立一个错误对象,返回错误的解释信息 throw new Error('XML解析错误:' + xmlDom.parseError.reason); } } else { //若是 上面两种方式都不支持 //建立一个错误对象,抛出您所使用的系统或浏览器不支持XML DOM! throw new Error('您所使用的系统或浏览器不支持XML DOM!'); } return xmlDom; //最后返回建立的xmlDOM对象 } //其次,咱们还必须跨浏览器序列化XML function serializeXML(xmlDom) { //序列化xml函数,接收xmlDOM对象对象 var xml = ''; //初始化一个变量等于空字符串 if (typeof XMLSerializer != 'undefined') { //判断XMLSerializer类型,不等于undefined,说明支持序列化 //给xml从新赋值,建立XMLSerializer对象,而且使用serializeToString方法序列化 xml = (new XMLSerializer()).serializeToString(xmlDom); //若是不支持XMLSerializer类型 } else if (typeof xmlDom.xml != 'undefined') { //判断IE方式xmlDOM对象下的xml属性是否等于undefined,不等于说明支持 //给xml从新赋值,序列化xml xml = xmlDom.xml; } else { //若是上面两种都不支持 //建立一个错误对象,抛出没法解析XML!错误信息 throw new Error('没法解析XML!'); } return xml; //最后返回序列化 }
上下文节点
上下文节点:咱们经过xmlDom这个对象实例调用方法,而xmlDom这个对象实例其实就是一个上下文节点,这个节点指针指向的是根,也就是root元素以前。那么若是咱们把这个指针指向user元素以前,那么结果就会有所变化。
经过xmlDom,而且使用root/user的路径
//经过xmlDom,而且使用root/user的路径 var user = xmlDom.selectSingleNode('root/user'); alert(user.tagName); //user
经过xmlDom.documentElement,而且使用user路径,省去了root
//经过xmlDom.documentElement,而且使用user路径,省去了root var user = xmlDom.documentElement.selectSingleNode('user'); alert(user.tagName); //user
经过xmlDom,而且使用user路径,省去了root
//经过xmlDom,而且使用user路径,省去了root var user = xmlDom.selectSingleNode('user'); alert(user.tagName); //找不到了,出错
PS:xmlDom和xmlDom.documentElement都是上下文节点,主要就是定位当前路径查找的指针,而xmlDom对象实例的指针就是在最根上。
XPath经常使用语法
经过user[n]来获取第n+1条节点,PS:XPath实际上是按1为起始值的,也就是经过索引位置来获取对应的标签
//经过user[n]来获取第n+1条节点,PS:XPath实际上是按1为起始值的 var user = xmlDom.selectSingleNode('root/user[1]'); alert(user.xml);
经过text()获取节点内的值
//经过text()获取节点内的值 var user = xmlDom.selectSingleNode('root/user/text()'); alert(user.xml); alert(user.nodeValue);
经过//user 表示在整个xml获取到user节点,不关心任何层次,经过双斜杠获取节点
//经过//user表示在整个xml获取到user节点,不关心任何层次 var user = xmlDom.selectSingleNode('//user'); alert(user.xml);
经过root//user表示在root包含的层次下获取到user节点,在root内不关心任何层次,经过指定节点下双斜杠获取节点
//经过root//user表示在root包含的层次下获取到user节点,在root内不关心任何层次 var user = xmlDom.selectSingleNode('root//user'); alert(user.tagName);
经过root/user[@id=6]表示获取user中id=6的节点,经过id获取指定节点
//经过root/user[@id=6]表示获取user中id=6的节点 var user = xmlDom.selectSingleNode('root/user[@id=6]'); alert(user.xml);
PS:更多的XPath语法,能够参考XPath手册或者XML DOM手册进行参考,这里只提供了最经常使用的语法。
selectNodes()方法,查找xml节点,返回相同名称的节点集合,有参参数是要查找的节点路径,此方法只支持IE而且是IE9如下
使用方式
XML DOM对象.selectNodes('要查找的节点路径')
var xml = '<root><user id="5">Lee</user><user id="6">Koko</user></root>'; //定义xml字符串 var xmldom = getXMLDOM(xml); //建立XML DOM对象,接收xml字符串 //经过XML DOM对象查找xml标签节点 var chzhao = xmldom.selectNodes('root/user'); //selectNodes()方法,查找xml节点,返回相同名称的节点集合,有参参数是要查找的节点路径,此方法只支持IE而且是IE9如下 alert(chzhao.length); //查看节点集合长度 alert(serializeXML(chzhao[0])); //经过索引,执行序列化函数,序列化查找到的节点 alert(chzhao[0].tagName); //经过索引打印查找到的元素标签名称 alert(chzhao[0].firstChild.nodeValue); //经过索引打印查找到的元素文本内容 //首先,咱们须要跨浏览器获取XML DOM function getXMLDOM(xmlStr) { //自定义跨浏览器建立xml DOM对象,接收一个参数xml字符串 var xmlDom = null; //初始化一个对象 if (typeof window.DOMParser != 'undefined') { //判断DOMParser类型不等于undefined说明支持 //建立DOMParser对象,而且建立xml DOM对象 xmlDom = (new DOMParser()).parseFromString(xmlStr, 'text/xml'); //获取错误信息的parsererror标签 var errors = xmlDom.getElementsByTagName('parsererror'); //判断错误信息标签返回集合长度大于0,说明xml有错误 if (errors.length > 0) { //建立一个错误对象,获取到第一个错误标签,而且获取到他的文本内容 throw new Error('XML解析错误:' + errors[0].firstChild.nodeValue); } //若是不支持DOMParser类型,尝试IE的方法 } else if (typeof window.ActiveXObject != 'undefined') { //判断ActiveXObject类型不等于undefined说明支持 var version = [ //建立一个数组,元素分别为3个xml版本 'MSXML2.DOMDocument.6.0', 'MSXML2.DOMDocument.3.0', 'MSXML2.DOMDocument' ]; for (var i = 0; i < version.length; i++) { //根据数组的长度循环次数 try { //尝试着执行每次循环到的xml版本,建立xml对象 xmlDom = new ActiveXObject(version[i]); } catch (e) { //若是出错跳过执行第二次循环 //跳过 } } xmlDom.loadXML(xmlStr); //载入xml字符串 if (xmlDom.parseError != 0) { //判断载入xml错误返回代码,若是不等于0说明xml有错 //建立一个错误对象,返回错误的解释信息 throw new Error('XML解析错误:' + xmlDom.parseError.reason); } } else { //若是 上面两种方式都不支持 //建立一个错误对象,抛出您所使用的系统或浏览器不支持XML DOM! throw new Error('您所使用的系统或浏览器不支持XML DOM!'); } return xmlDom; //最后返回建立的xmlDOM对象 } //其次,咱们还必须跨浏览器序列化XML function serializeXML(xmlDom) { //序列化xml函数,接收xmlDOM对象对象 var xml = ''; //初始化一个变量等于空字符串 if (typeof XMLSerializer != 'undefined') { //判断XMLSerializer类型,不等于undefined,说明支持序列化 //给xml从新赋值,建立XMLSerializer对象,而且使用serializeToString方法序列化 xml = (new XMLSerializer()).serializeToString(xmlDom); //若是不支持XMLSerializer类型 } else if (typeof xmlDom.xml != 'undefined') { //判断IE方式xmlDOM对象下的xml属性是否等于undefined,不等于说明支持 //给xml从新赋值,序列化xml xml = xmlDom.xml; } else { //若是上面两种都不支持 //建立一个错误对象,抛出没法解析XML!错误信息 throw new Error('没法解析XML!'); } return xml; //最后返回序列化 }
二.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()方法。
XPathResult对象
XPathEvaluator类型
第一个方式,首先new XPathEvaluator类型,而后执行XPathEvaluator类型下的evaluate()方法来建立XPathResult对象
evaluate()方法,建立XPathResult对象有5个参数,1要查找的xml标签路径,2上下文节点对象也就是XMLDOM对象,3命名空间求解器(一般是null),4返回结果类型,5保存结果的XPathResult对象(一般是null)。
使用方式:
XPathResult对象.evaluate(要查找的xml标签路径,XMLDOM对象,null,返回结果类型,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.获取一个节点集合。
两种方式建立XPathResult对象
使用XPathEvaluator对象建立XPathResult
var xml = '<root><user id="5">Lee</user><user id="6">Koko</user></root>'; //定义xml字符串 var xmldom = getXMLDOM(xml); //建立XML DOM对象,接收xml字符串 //使用XPathEvaluator对象建立XPathResult var eva = new XPathEvaluator(); //建立XPathResult对象 //evaluate()方法,建立XPathResult对象有5个参数,1要查找的xml标签路径,2上下文节点对象也就是XMLDOM对象,3命名空间求解器(一般是null),4返回结果类型,5保存结果的XPathResult对象(一般是null)。 var result = eva.evaluate('root/user', xmldom , null,XPathResult.FIRST_ORDERED_NODE_TYPE, null); alert(result); //返回单一节点集合 //首先,咱们须要跨浏览器获取XML DOM function getXMLDOM(xmlStr) { //自定义跨浏览器建立xml DOM对象,接收一个参数xml字符串 var xmlDom = null; //初始化一个对象 if (typeof window.DOMParser != 'undefined') { //判断DOMParser类型不等于undefined说明支持 //建立DOMParser对象,而且建立xml DOM对象 xmlDom = (new DOMParser()).parseFromString(xmlStr, 'text/xml'); //获取错误信息的parsererror标签 var errors = xmlDom.getElementsByTagName('parsererror'); //判断错误信息标签返回集合长度大于0,说明xml有错误 if (errors.length > 0) { //建立一个错误对象,获取到第一个错误标签,而且获取到他的文本内容 throw new Error('XML解析错误:' + errors[0].firstChild.nodeValue); } //若是不支持DOMParser类型,尝试IE的方法 } else if (typeof window.ActiveXObject != 'undefined') { //判断ActiveXObject类型不等于undefined说明支持 var version = [ //建立一个数组,元素分别为3个xml版本 'MSXML2.DOMDocument.6.0', 'MSXML2.DOMDocument.3.0', 'MSXML2.DOMDocument' ]; for (var i = 0; i < version.length; i++) { //根据数组的长度循环次数 try { //尝试着执行每次循环到的xml版本,建立xml对象 xmlDom = new ActiveXObject(version[i]); } catch (e) { //若是出错跳过执行第二次循环 //跳过 } } xmlDom.loadXML(xmlStr); //载入xml字符串 if (xmlDom.parseError != 0) { //判断载入xml错误返回代码,若是不等于0说明xml有错 //建立一个错误对象,返回错误的解释信息 throw new Error('XML解析错误:' + xmlDom.parseError.reason); } } else { //若是 上面两种方式都不支持 //建立一个错误对象,抛出您所使用的系统或浏览器不支持XML DOM! throw new Error('您所使用的系统或浏览器不支持XML DOM!'); } return xmlDom; //最后返回建立的xmlDOM对象 } //其次,咱们还必须跨浏览器序列化XML function serializeXML(xmlDom) { //序列化xml函数,接收xmlDOM对象对象 var xml = ''; //初始化一个变量等于空字符串 if (typeof XMLSerializer != 'undefined') { //判断XMLSerializer类型,不等于undefined,说明支持序列化 //给xml从新赋值,建立XMLSerializer对象,而且使用serializeToString方法序列化 xml = (new XMLSerializer()).serializeToString(xmlDom); //若是不支持XMLSerializer类型 } else if (typeof xmlDom.xml != 'undefined') { //判断IE方式xmlDOM对象下的xml属性是否等于undefined,不等于说明支持 //给xml从新赋值,序列化xml xml = xmlDom.xml; } else { //若是上面两种都不支持 //建立一个错误对象,抛出没法解析XML!错误信息 throw new Error('没法解析XML!'); } return xml; //最后返回序列化 }
使用上下文节点对象(xmlDom)建立XPathResult对象,就是直接在XMLDOM对象执行evaluate()方法
var xml = '<root><user id="5">Lee</user><user id="6">Koko</user></root>'; //定义xml字符串 var xmldom = getXMLDOM(xml); //建立XML DOM对象,接收xml字符串 //使用上下文节点对象(xmlDom)建立XPathResult var result = xmldom.evaluate('root/user', xmldom, null,XPathResult.FIRST_ORDERED_NODE_TYPE, null); alert(result); //返回单一节点集合 //首先,咱们须要跨浏览器获取XML DOM function getXMLDOM(xmlStr) { //自定义跨浏览器建立xml DOM对象,接收一个参数xml字符串 var xmlDom = null; //初始化一个对象 if (typeof window.DOMParser != 'undefined') { //判断DOMParser类型不等于undefined说明支持 //建立DOMParser对象,而且建立xml DOM对象 xmlDom = (new DOMParser()).parseFromString(xmlStr, 'text/xml'); //获取错误信息的parsererror标签 var errors = xmlDom.getElementsByTagName('parsererror'); //判断错误信息标签返回集合长度大于0,说明xml有错误 if (errors.length > 0) { //建立一个错误对象,获取到第一个错误标签,而且获取到他的文本内容 throw new Error('XML解析错误:' + errors[0].firstChild.nodeValue); } //若是不支持DOMParser类型,尝试IE的方法 } else if (typeof window.ActiveXObject != 'undefined') { //判断ActiveXObject类型不等于undefined说明支持 var version = [ //建立一个数组,元素分别为3个xml版本 'MSXML2.DOMDocument.6.0', 'MSXML2.DOMDocument.3.0', 'MSXML2.DOMDocument' ]; for (var i = 0; i < version.length; i++) { //根据数组的长度循环次数 try { //尝试着执行每次循环到的xml版本,建立xml对象 xmlDom = new ActiveXObject(version[i]); } catch (e) { //若是出错跳过执行第二次循环 //跳过 } } xmlDom.loadXML(xmlStr); //载入xml字符串 if (xmlDom.parseError != 0) { //判断载入xml错误返回代码,若是不等于0说明xml有错 //建立一个错误对象,返回错误的解释信息 throw new Error('XML解析错误:' + xmlDom.parseError.reason); } } else { //若是 上面两种方式都不支持 //建立一个错误对象,抛出您所使用的系统或浏览器不支持XML DOM! throw new Error('您所使用的系统或浏览器不支持XML DOM!'); } return xmlDom; //最后返回建立的xmlDOM对象 } //其次,咱们还必须跨浏览器序列化XML function serializeXML(xmlDom) { //序列化xml函数,接收xmlDOM对象对象 var xml = ''; //初始化一个变量等于空字符串 if (typeof XMLSerializer != 'undefined') { //判断XMLSerializer类型,不等于undefined,说明支持序列化 //给xml从新赋值,建立XMLSerializer对象,而且使用serializeToString方法序列化 xml = (new XMLSerializer()).serializeToString(xmlDom); //若是不支持XMLSerializer类型 } else if (typeof xmlDom.xml != 'undefined') { //判断IE方式xmlDOM对象下的xml属性是否等于undefined,不等于说明支持 //给xml从新赋值,序列化xml xml = xmlDom.xml; } else { //若是上面两种都不支持 //建立一个错误对象,抛出没法解析XML!错误信息 throw new Error('没法解析XML!'); } return xml; //最后返回序列化 }
相对而言,第二种简单方便一点,但evaluate方法有五个属性:1.XPath路径、2.上下文节点对象、3.命名空间求解器(一般是null)、4.返回结果类型、5保存结果的XPathResult对象(一般是null)。
获取xml节点
1.获取一个单一节点
singleNodeValue属性,获得XPathResult对象里的单一节点对象,获取返回类型XPathResult.FIRST_ORDERED_NODE_TYPE的节点对象
var xml = '<root><user id="5">Lee</user><user id="6">Koko</user></root>'; //定义xml字符串 var xmldom = getXMLDOM(xml); //建立XML DOM对象,接收xml字符串 var result = xmldom.evaluate('root/user', xmldom, null,XPathResult.FIRST_ORDERED_NODE_TYPE, null); if (result !== null) { //singleNodeValue属性,获得XPathResult对象里的节点对象 alert(result.singleNodeValue.tagName); //打印出节点的标签名称 } //首先,咱们须要跨浏览器获取XML DOM function getXMLDOM(xmlStr) { //自定义跨浏览器建立xml DOM对象,接收一个参数xml字符串 var xmlDom = null; //初始化一个对象 if (typeof window.DOMParser != 'undefined') { //判断DOMParser类型不等于undefined说明支持 //建立DOMParser对象,而且建立xml DOM对象 xmlDom = (new DOMParser()).parseFromString(xmlStr, 'text/xml'); //获取错误信息的parsererror标签 var errors = xmlDom.getElementsByTagName('parsererror'); //判断错误信息标签返回集合长度大于0,说明xml有错误 if (errors.length > 0) { //建立一个错误对象,获取到第一个错误标签,而且获取到他的文本内容 throw new Error('XML解析错误:' + errors[0].firstChild.nodeValue); } //若是不支持DOMParser类型,尝试IE的方法 } else if (typeof window.ActiveXObject != 'undefined') { //判断ActiveXObject类型不等于undefined说明支持 var version = [ //建立一个数组,元素分别为3个xml版本 'MSXML2.DOMDocument.6.0', 'MSXML2.DOMDocument.3.0', 'MSXML2.DOMDocument' ]; for (var i = 0; i < version.length; i++) { //根据数组的长度循环次数 try { //尝试着执行每次循环到的xml版本,建立xml对象 xmlDom = new ActiveXObject(version[i]); } catch (e) { //若是出错跳过执行第二次循环 //跳过 } } xmlDom.loadXML(xmlStr); //载入xml字符串 if (xmlDom.parseError != 0) { //判断载入xml错误返回代码,若是不等于0说明xml有错 //建立一个错误对象,返回错误的解释信息 throw new Error('XML解析错误:' + xmlDom.parseError.reason); } } else { //若是 上面两种方式都不支持 //建立一个错误对象,抛出您所使用的系统或浏览器不支持XML DOM! throw new Error('您所使用的系统或浏览器不支持XML DOM!'); } return xmlDom; //最后返回建立的xmlDOM对象 } //其次,咱们还必须跨浏览器序列化XML function serializeXML(xmlDom) { //序列化xml函数,接收xmlDOM对象对象 var xml = ''; //初始化一个变量等于空字符串 if (typeof XMLSerializer != 'undefined') { //判断XMLSerializer类型,不等于undefined,说明支持序列化 //给xml从新赋值,建立XMLSerializer对象,而且使用serializeToString方法序列化 xml = (new XMLSerializer()).serializeToString(xmlDom); //若是不支持XMLSerializer类型 } else if (typeof xmlDom.xml != 'undefined') { //判断IE方式xmlDOM对象下的xml属性是否等于undefined,不等于说明支持 //给xml从新赋值,序列化xml xml = xmlDom.xml; } else { //若是上面两种都不支持 //建立一个错误对象,抛出没法解析XML!错误信息 throw new Error('没法解析XML!'); } return xml; //最后返回序列化 }
2.获取节点集合
iterateNext()方法,获得XPathResult对象里的集合节点对象,获取返回类型XPathResult.ORDERED_NODE_ITERATOR_TYPE的节点对象
var xml = '<root><user id="5">Lee</user><user id="6">Koko</user></root>'; //定义xml字符串 var xmldom = getXMLDOM(xml); //建立XML DOM对象,接收xml字符串 //使用上下文节点对象(xmlDom)建立XPathResult,返回类型为xml标签集合 var result = xmldom.evaluate('root/user', xmldom, null,XPathResult.ORDERED_NODE_ITERATOR_TYPE, null); if (result !== null) { //判断集合不为空 var nodes = []; //建立空数组 var node = result.iterateNext(); //获取到集合里的一个标签对象 while (node !== null) { //判断获取集合里的一个标签对象不为空,循环这个节点集合 nodes.push(node); //将循环到的节点添加到初始化数组 node = result.iterateNext(); //再次取集合里的一个标签对象,进行迭代 } } alert(serializeXML(nodes[0])); //序列化打印第一个节点 alert(serializeXML(nodes[1])); //序列化打印第二个节点 //首先,咱们须要跨浏览器获取XML DOM function getXMLDOM(xmlStr) { //自定义跨浏览器建立xml DOM对象,接收一个参数xml字符串 var xmlDom = null; //初始化一个对象 if (typeof window.DOMParser != 'undefined') { //判断DOMParser类型不等于undefined说明支持 //建立DOMParser对象,而且建立xml DOM对象 xmlDom = (new DOMParser()).parseFromString(xmlStr, 'text/xml'); //获取错误信息的parsererror标签 var errors = xmlDom.getElementsByTagName('parsererror'); //判断错误信息标签返回集合长度大于0,说明xml有错误 if (errors.length > 0) { //建立一个错误对象,获取到第一个错误标签,而且获取到他的文本内容 throw new Error('XML解析错误:' + errors[0].firstChild.nodeValue); } //若是不支持DOMParser类型,尝试IE的方法 } else if (typeof window.ActiveXObject != 'undefined') { //判断ActiveXObject类型不等于undefined说明支持 var version = [ //建立一个数组,元素分别为3个xml版本 'MSXML2.DOMDocument.6.0', 'MSXML2.DOMDocument.3.0', 'MSXML2.DOMDocument' ]; for (var i = 0; i < version.length; i++) { //根据数组的长度循环次数 try { //尝试着执行每次循环到的xml版本,建立xml对象 xmlDom = new ActiveXObject(version[i]); } catch (e) { //若是出错跳过执行第二次循环 //跳过 } } xmlDom.loadXML(xmlStr); //载入xml字符串 if (xmlDom.parseError != 0) { //判断载入xml错误返回代码,若是不等于0说明xml有错 //建立一个错误对象,返回错误的解释信息 throw new Error('XML解析错误:' + xmlDom.parseError.reason); } } else { //若是 上面两种方式都不支持 //建立一个错误对象,抛出您所使用的系统或浏览器不支持XML DOM! throw new Error('您所使用的系统或浏览器不支持XML DOM!'); } return xmlDom; //最后返回建立的xmlDOM对象 } //其次,咱们还必须跨浏览器序列化XML function serializeXML(xmlDom) { //序列化xml函数,接收xmlDOM对象对象 var xml = ''; //初始化一个变量等于空字符串 if (typeof XMLSerializer != 'undefined') { //判断XMLSerializer类型,不等于undefined,说明支持序列化 //给xml从新赋值,建立XMLSerializer对象,而且使用serializeToString方法序列化 xml = (new XMLSerializer()).serializeToString(xmlDom); //若是不支持XMLSerializer类型 } else if (typeof xmlDom.xml != 'undefined') { //判断IE方式xmlDOM对象下的xml属性是否等于undefined,不等于说明支持 //给xml从新赋值,序列化xml xml = xmlDom.xml; } else { //若是上面两种都不支持 //建立一个错误对象,抛出没法解析XML!错误信息 throw new Error('没法解析XML!'); } return xml; //最后返回序列化 }
PS:节点集合的获取方式,是经过迭代器遍历而来的,咱们保存到数据中就模拟出IE类似的风格。
三.XPath跨浏览器兼容
若是要作W3C和IE的跨浏览器兼容,咱们要思考几个问题:1.若是传递一个节点的下标,IE是从0开始计算,W3C从1开始计算,能够经过传递获取下标进行增1减1的操做来进行。2.独有的功能放弃,为了保证跨浏览器。3.只获取单一节点和节点列表便可,基本能够完成全部的操做。
跨浏览器获取单一节点
var xml = '<root><user id="5">Lee</user><user id="6">Koko</user></root>'; //定义xml字符串 var xmldom = getXMLDOM(xml); //建立XML DOM对象,接收xml字符串 var jied = selectSingleNode(xmldom,'root/user'); //执行跨浏览器获取单一节点函数 alert(serializeXML(jied)); //序列化节点标签 //跨浏览器获取单一节点,返回单一节点对象 function selectSingleNode(xmlDom, xpath) { //加收两个参数,参数1XML DOM对象,参数二要查找的标签路径 var node = null; //初始化 if (typeof xmlDom.evaluate != 'undefined') { //判断XML DOM对象下的evaluate方法不等于undefined,说明支持,就用ie9如下的方式 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') { //w3c方式 node = xmlDom.selectSingleNode(xpath); } return node; } //首先,咱们须要跨浏览器获取XML DOM function getXMLDOM(xmlStr) { //自定义跨浏览器建立xml DOM对象,接收一个参数xml字符串 var xmlDom = null; //初始化一个对象 if (typeof window.DOMParser != 'undefined') { //判断DOMParser类型不等于undefined说明支持 //建立DOMParser对象,而且建立xml DOM对象 xmlDom = (new DOMParser()).parseFromString(xmlStr, 'text/xml'); //获取错误信息的parsererror标签 var errors = xmlDom.getElementsByTagName('parsererror'); //判断错误信息标签返回集合长度大于0,说明xml有错误 if (errors.length > 0) { //建立一个错误对象,获取到第一个错误标签,而且获取到他的文本内容 throw new Error('XML解析错误:' + errors[0].firstChild.nodeValue); } //若是不支持DOMParser类型,尝试IE的方法 } else if (typeof window.ActiveXObject != 'undefined') { //判断ActiveXObject类型不等于undefined说明支持 var version = [ //建立一个数组,元素分别为3个xml版本 'MSXML2.DOMDocument.6.0', 'MSXML2.DOMDocument.3.0', 'MSXML2.DOMDocument' ]; for (var i = 0; i < version.length; i++) { //根据数组的长度循环次数 try { //尝试着执行每次循环到的xml版本,建立xml对象 xmlDom = new ActiveXObject(version[i]); } catch (e) { //若是出错跳过执行第二次循环 //跳过 } } xmlDom.loadXML(xmlStr); //载入xml字符串 if (xmlDom.parseError != 0) { //判断载入xml错误返回代码,若是不等于0说明xml有错 //建立一个错误对象,返回错误的解释信息 throw new Error('XML解析错误:' + xmlDom.parseError.reason); } } else { //若是 上面两种方式都不支持 //建立一个错误对象,抛出您所使用的系统或浏览器不支持XML DOM! throw new Error('您所使用的系统或浏览器不支持XML DOM!'); } return xmlDom; //最后返回建立的xmlDOM对象 } //其次,咱们还必须跨浏览器序列化XML function serializeXML(xmlDom) { //序列化xml函数,接收xmlDOM对象对象 var xml = ''; //初始化一个变量等于空字符串 if (typeof XMLSerializer != 'undefined') { //判断XMLSerializer类型,不等于undefined,说明支持序列化 //给xml从新赋值,建立XMLSerializer对象,而且使用serializeToString方法序列化 xml = (new XMLSerializer()).serializeToString(xmlDom); //若是不支持XMLSerializer类型 } else if (typeof xmlDom.xml != 'undefined') { //判断IE方式xmlDOM对象下的xml属性是否等于undefined,不等于说明支持 //给xml从新赋值,序列化xml xml = xmlDom.xml; } else { //若是上面两种都不支持 //建立一个错误对象,抛出没法解析XML!错误信息 throw new Error('没法解析XML!'); } return xml; //最后返回序列化 }
跨浏览器获取节点集合
var xml = '<root><user id="5">Lee</user><user id="6">Koko</user></root>'; //定义xml字符串 var xmldom = getXMLDOM(xml); //建立XML DOM对象,接收xml字符串 var jied = selectNodes(xmldom,'root/user'); //执行跨浏览器获取集合节点函数 alert(serializeXML(jied[0])); //序列化节点标签 //跨浏览器获取节点集合,返回节点集合 function selectNodes(xmlDom, xpath) { //接收两个参数,参数1XML DOM对象,参数2要查找的节点标签路径 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; } //首先,咱们须要跨浏览器获取XML DOM function getXMLDOM(xmlStr) { //自定义跨浏览器建立xml DOM对象,接收一个参数xml字符串 var xmlDom = null; //初始化一个对象 if (typeof window.DOMParser != 'undefined') { //判断DOMParser类型不等于undefined说明支持 //建立DOMParser对象,而且建立xml DOM对象 xmlDom = (new DOMParser()).parseFromString(xmlStr, 'text/xml'); //获取错误信息的parsererror标签 var errors = xmlDom.getElementsByTagName('parsererror'); //判断错误信息标签返回集合长度大于0,说明xml有错误 if (errors.length > 0) { //建立一个错误对象,获取到第一个错误标签,而且获取到他的文本内容 throw new Error('XML解析错误:' + errors[0].firstChild.nodeValue); } //若是不支持DOMParser类型,尝试IE的方法 } else if (typeof window.ActiveXObject != 'undefined') { //判断ActiveXObject类型不等于undefined说明支持 var version = [ //建立一个数组,元素分别为3个xml版本 'MSXML2.DOMDocument.6.0', 'MSXML2.DOMDocument.3.0', 'MSXML2.DOMDocument' ]; for (var i = 0; i < version.length; i++) { //根据数组的长度循环次数 try { //尝试着执行每次循环到的xml版本,建立xml对象 xmlDom = new ActiveXObject(version[i]); } catch (e) { //若是出错跳过执行第二次循环 //跳过 } } xmlDom.loadXML(xmlStr); //载入xml字符串 if (xmlDom.parseError != 0) { //判断载入xml错误返回代码,若是不等于0说明xml有错 //建立一个错误对象,返回错误的解释信息 throw new Error('XML解析错误:' + xmlDom.parseError.reason); } } else { //若是 上面两种方式都不支持 //建立一个错误对象,抛出您所使用的系统或浏览器不支持XML DOM! throw new Error('您所使用的系统或浏览器不支持XML DOM!'); } return xmlDom; //最后返回建立的xmlDOM对象 } //其次,咱们还必须跨浏览器序列化XML function serializeXML(xmlDom) { //序列化xml函数,接收xmlDOM对象对象 var xml = ''; //初始化一个变量等于空字符串 if (typeof XMLSerializer != 'undefined') { //判断XMLSerializer类型,不等于undefined,说明支持序列化 //给xml从新赋值,建立XMLSerializer对象,而且使用serializeToString方法序列化 xml = (new XMLSerializer()).serializeToString(xmlDom); //若是不支持XMLSerializer类型 } else if (typeof xmlDom.xml != 'undefined') { //判断IE方式xmlDOM对象下的xml属性是否等于undefined,不等于说明支持 //给xml从新赋值,序列化xml xml = xmlDom.xml; } else { //若是上面两种都不支持 //建立一个错误对象,抛出没法解析XML!错误信息 throw new Error('没法解析XML!'); } return xml; //最后返回序列化 }
PS:在传递xpath路径时,没有作验证判断是否合法,有兴趣的同窗能够自行完成。在XML还有一个重要章节是XSLT和EX4,因为在使用频率的缘故,咱们暂且搁置。