第一百二十六节,JavaScript,XPath操作xml节点

第一百二十六节,JavaScript,XPath操作xml节点

 

学习要点:

1.IE中的XPath

2.W3C中的XPath

3.XPath跨浏览器兼容

 

XPath是一种节点查找手段,对比之前使用标准DOM去查找XML中的节点方式,大大降低了查找难度,方便开发者使用。但是,DOM3级以前的标准并没有就XPath做出规范;直到DOM3在首次推荐到标准规范行列。大部分浏览器实现了这个标准,IE则以自己的方式实现了XPath。

 

一.IE中的XPath

在IE8及之前的浏览器,XPath是采用内置基于ActiveX的XML DOM文档对象实现的。在每一个节点上提供了两个方法:selectSingleNode()和selectNodes()。

selectSingleNode()方法接受一个XPath模式(也就是查找路径),找到匹配的第一个节点并将它返回,没有则返回null。

selectSingleNode()方法,查找xml节点,查找单一节点如果有相同的节点只返回第一个节点,有参参数是要查找的节点路径,此方法只支持IE并且是IE9以下
使用方式
XML DOM对象.selectSingleNode('要查找的节点路径')

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重新赋值,序列化xmlxml = 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路径,省去了rootvar user = xmlDom.documentElement.selectSingleNode('user');alert(user.tagName);                                                //user

通过xmlDom,并且使用user路径,省去了root

//通过xmlDom,并且使用user路径,省去了rootvar 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重新赋值,序列化xmlxml = 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重新赋值,序列化xmlxml = 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重新赋值,序列化xmlxml = 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重新赋值,序列化xmlxml = 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重新赋值,序列化xmlxml = 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重新赋值,序列化xmlxml = 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重新赋值,序列化xmlxml = xmlDom.xml;} else { //如果上面两种都不支持//创建一个错误对象,抛出无法解析XML!错误信息throw new Error('无法解析XML!');}return xml; //最后返回序列化
}

PS:在传递xpath路径时,没有做验证判断是否合法,有兴趣的同学可以自行完成。在XML还有一个重要章节是XSLT和EX4,由于在使用频率的缘故,我们暂且搁置。

转载于:https://www.cnblogs.com/adc8868/p/6216078.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/429750.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

matlab 控制实验指导,智能控制系统-实验指导书-实验一-BP算法的MATLAB实现

实验一、BP算法的MATLAB实现一、实验目的1、了解MATLAB集成开发环境2、了解MATLAB编程基本方法3、加深对&#xff22;&#xff30;算法的理解和掌握二、实验内容1、MATLAB基本指令和语法。2、&#xff22;&#xff30;算法的MATLAB实现三、实验步骤1、熟悉MATLAB开发环境2、输入…

电力电子技术 matlab仿真指导,在_电力电子技术_课程教学中展开Matlab仿真训练_唐贤伦...

教学改革广角中国电力教育2009年10月上 总第146期 “电力电子技术”是电气工程及其自动化等专业的重要专业基础课&#xff0c;也是实用性、工程性和综合性很强的课程。作为自动化、电气工程及其自动化等专业的学生&#xff0c;学好这门课程将为后续专业课的学习和今后的工作打下…

Python补充01 序列的方法

作者&#xff1a;Vamei 出处&#xff1a;http://www.cnblogs.com/vamei 欢迎转载&#xff0c;也请保留这段声明。谢谢&#xff01; 在快速教程中&#xff0c;我们了解了最基本的序列(sequence)。回忆一下&#xff0c;序列包含有定值表(tuple)和表(list)。此外&#xff0c;字符串…

java socketchannel api,SocketChannel API

Netty是当前非常流行的网络通讯框架&#xff0c;当程序对网络数据处理时&#xff0c;需要保证高并发和高可靠&#xff0c;底层就可以用Netty支撑。本套课程详细讲解了Netty核心技术点&#xff0c;同时进行底层机制和源码剖析&#xff0c;并编写了大量的应用实例。通过学习可以快…

CLR via C# 阅读 笔记

初读  CLR Via C# 有一些 名词需要记忆&#xff1a; 1、CLR: Common Language Runtime (公共语言运行时) 可有多种编程语言使用的Runtime. 其核心功能是&#xff1a; 内存管理、 程序集加载、 安全性、 异常处理和线程同步等&#xff1b; 2、 Managed Module (托管模块) 托管模…

php异步轮询如何实现,深入剖析JavaScript异步之事件轮询

本篇文章给大家带来的内容是关于深入剖析JavsScript异步之事件轮询&#xff0c;有一定的参考价值&#xff0c;有需要的朋友可以参考一下&#xff0c;希望对你有所帮助。JavsScript 是一门单线程的编程语言&#xff0c;这就意味着一个时间里只能处理一件事&#xff0c;也就是说 …

ECMAScript 实现继承的几种方式

1. 原形链 function Father() { this.fatherName "licus"; } function Children() { this.chidrenName "king"; } Children.prototype new Father(); 2.借用构造函数 function Father() { this.fatherName "licus"; } function Children() {…

微信小程序php实现登陆的代码,微信小程序实现微信登录

步骤&#xff1a;1.调用wx.login得到code返回的结果示例&#xff1a;{code:"051nI5Pa1XJkDs0773Pa1OWYOa1nI5PF"errMsg:"login:ok"}2.拿code换取session_key与openid这里使用服务端来请求&#xff0c;以php为例$code $this->input->post(code);$jso…

《C++ Primer Plus(第六版)》(25)(第十三章 类继承 笔记)

1.派生类构造函数的要点: 首先创建基类对象; 应通过成员初始化列表将基类的初始化信息传递给基类的构造函数; 派生类构造函数应初始化新增的数据成员 2.首先执行派生类的析构函数,然后自动调用基类的析构函数. 3.基类指针可以在不进行显式类型转换的情况下指向派生类对象,基类引…

php实际应用小例子,PHP4实际应用经验篇(6)

现在&#xff0c;你已经明白PHP允许你嵌套条件语句。然而&#xff0c;如果你再看看那个用来示范此概念的例子时你将同意那是既复杂又令人感到可怕。--------------------------------------------------------------------------------if($day"Thursday"){if($time&q…

electron知识点

1.打开chrome开发工具栏&#xff1a; BrowserWindow.openDevTools(); 转载于:https://www.cnblogs.com/cag2050/p/6227987.html

oracle 12c缩容磁盘组,oracle 表收缩

当使用delete表数据后&#xff0c;空间无法释放&#xff0c;可以使用表收缩释放表空间&#xff1b;注意&#xff1a;当delete表大量数据的时候要注意undo&#xff0c;可以使用&#xff1a;alter table emp nologging; 让其不生产日志一、表的增长方式当表被创建后&#xff0…

php解决与处理网站高并发 大流量访问的方法

方法/步骤 首先&#xff0c;确认服务器硬件是否足够支持当前的流量 普通的P4服务器一般最多能支持每天10万独立IP&#xff0c;如果访问量比这个还要大&#xff0c; 那么必须首先配置一台更高性能的专用服务器才能解决问题 &#xff0c;否则怎么优化都不可能彻底解决性能问题。 …

oracle 自动表分析,Oracle自动分析索引,表

--分析表REATE OR REPLACE PROCEDURE analyze_tables IS--rec integer;v_date1 number(10);v_date2 number(10);V_SQL varchar2(512);v_msg varchar2(512);BEGINFOR rec IN (SELECT table_name FROM user_tables)LOOPv_date1 : dbms_utility.get_time;V_SQL : ANALYZE TABLE |…

JavaScript 函数(作用域以及闭包)

JavaScript 函数&#xff08;作用域以及闭包&#xff09; ・执行环境及作用域 执行环境定义了变量或函数有权访问的其他数据。 每个执行环境都有一个与之关联的变量对象&#xff0c;环境中定义的所有变量或函数都保存在这个对象中&#xff0c; 虽然我们编写的代码无法访问这个对…

十天学会PHP(第五版),十天学会php之第五天

十天学会php之第五天学习目的&#xff1a;学会读取数据先看两个函数&#xff1a;1、mysql_query送出一个 query 字符串。 语法: int mysql_query(string query, int [link_identifier]); 返回值: 整数本函数送出 query 字符串供 MySQL 做相关的处理或者执行。若没有指定 link_i…

《DSP using MATLAB》第6章开始了

看到第6章了&#xff0c;标记一下&#xff0c;全书近一半&#xff0c;继续加油 构建滤波器的三种元件&#xff1a; 下面是函数floor和size的部分帮助截图 转载于:https://www.cnblogs.com/ky027wh-sx/p/6235509.html

codeql php,使用codeql 挖掘 ofcms

前言网上关于codeql的文章并不多&#xff0c;国内现在对codeql的研究相对比较少&#xff0c;可能是因为codeql暂时没有中文文档&#xff0c;资料也相对较少&#xff0c;需要比较好的英语功底&#xff0c;但是我认为在随着代码量越来越多&#xff0c;传统的自动化漏洞挖掘工具的…

谈谈个人代码对团队合作影响

这几天正接手一个项目&#xff0c;属于后期功能拓展&#xff0c;要拓展这个项目&#xff0c;一定程度上要看到源码的部分&#xff0c;然后烦心的事情就来了&#xff0c;这代码写的真是让人挺无语的&#xff0c;原先写完整个项目的是已有多年工作经验的开发者&#xff0c;但是整…

php 连接符.,PHP怎么在数字之间添加连接符

PHP实现数字之间添加连接符&#xff0c;我们可以通过PHP中的for循环思想来实现。这里的连接符指的是“-”符号。推荐参考&#xff1a;《PHP教程》那么对于新手来说&#xff0c;可能有一定难度。下面我们就通过简单的代码示例&#xff0c;给大家介绍PHP给数字之间添加连字符的实…