首页 > 代码库 > 第一百二十六节,JavaScript,XPath操作xml节点

第一百二十六节,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重新赋值,序列化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; //最后返回序列化
}

 

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