• JavaScript XML 兼容处理,序列化和反序列化以及回调事件


    浏览器中XML DOM的支持

    IE中通过ActiveXObject实现了XML的支持,存在一下几个版本:
    Microsoft.XmlDom,MSXML2.DOMDocument,MSXML2.DOMDocument.3.0,MSXML2.DOMDocument.4.0,MXXML2.DOMDocument.5.0

    IE678使用ActiveXObject来实现XML支持,可以通过loadXML()来传入XML字符串;
    在现代浏览器下通过document.implementation.createDocument来实现XML支持,
    反序列化需要通过DOMParse对象以及parseFromString方法来完成。

    对于载入文档完成后的事件触发,IE678使用的是onreadystatechange事件以及判断readyState属性来得知状态;
    对于现代浏览器使用的是onload事件。

    对于一个XML对象,IE678提供了xml属性序列化;
    对于现代浏览器,需要(new XMLSerializer).serializeToString来序列化。

    如上分析,想要实现兼容,
    可以通过document.prototype.loadXML来实现现代浏览器的loadXML兼容;
    可以通过ES5的Object.defineProperty来定义现代浏览器的readyState属性,在set为4的时候触发onreadystatechange事件;
    可以通过ES5的Object.defineProperty来定义现代浏览器的xml属性,读取的时候通过XMLSerializer对象来序列化。

    不考虑异常和错误,测试代码如下:

      1 <!DOCTYPE html>
      2 <html>
      3 <head>
      4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
      5 <style rel="stylesheet" type="text/css">
      6 </style>
      7 <script type="text/javascript">
      8 function createXMLDOM() {
      9     if(!createXMLDOM.cache){
     10         // 现代浏览器分支.
     11         if(document.implementation && document.implementation.createDocument){
     12             createXMLDOM.cache=function(){
     13                 var xmldom=document.implementation.createDocument("","",null);
     14 
     15                 // 兼容onreadystatechange方法.
     16                 _fix_onreadystatechange.call(xmldom);
     17                 // 添加一个触发事件.
     18                 xmldom.addEventListener("load",function(){
     19                     // 设置readyState为4.被动触发onreadystatechange事件.
     20                     this.readyState=4;
     21                 },false);
     22                 return xmldom;
     23             };
     24             // 兼容loadXML方法.
     25             _fix_loadXML();
     26             // 兼容xml属性
     27             _fix_xml();
     28             return createXMLDOM.cache();
     29         }
     30         // IE678分支.
     31         else if(window.ActiveXObject){
     32             var vs=["MSXML2.DOMDocument.5.0","MSXML2.DOMDocument.4.0",
     33             "MSXML2.DOMDocument.3.0","MSXML2.DOMDocument",
     34             "Microsoft.XmlDom"];
     35             for(var i=0,j=vs.length;i<j;i++){
     36                 try{
     37                     var oxmldom=new ActiveXObject(vs[i]);
     38                     createXMLDOM.cache=new Function("x","return new ActiveXObject('"+vs[i]+"');");
     39 
     40                     return oxmldom;
     41                 }
     42                 catch(ex){}
     43             }
     44         }
     45         // 都不兼容.
     46         else{
     47             createXMLDOM.cache=new Function("return null;");
     48             return null;
     49         }
     50     }
     51     else{
     52         return createXMLDOM.cache();
     53     }
     54 }
     55 
     56 /* loadXML的兼容处理.现代浏览器. */
     57 function _fix_loadXML(){
     58     Document.prototype.loadXML=function(sxml){
     59         var oparse=new DOMParser();
     60         var oxmldom=oparse.parseFromString(sxml, "text/xml");
     61         while(this.firstChild){
     62             this.removeChild(this.firstChild);
     63         }
     64         for(var i=0,j=oxmldom.childNodes.length;i<j;i++){
     65             // 获取另一个文档的某个节点以及所有子节点.
     66             var onewnode=this.importNode(oxmldom.childNodes[i],true);
     67             // 添加到该文档中.
     68             this.appendChild(onewnode);
     69         }
     70         // 这里修正readyState属性.
     71         this.readyState=4;
     72     };
     73 }
     74 /* 处理onreadystatechange的兼容. */
     75 function _fix_onreadystatechange(){
     76     if(Object.defineProperty){
     77         Object.defineProperty(this,"readyState",{
     78             get:function(){
     79                 return this.__readyState__;
     80             },
     81             set:function(i){
     82                 this.__readyState__=i;
     83                 this.onreadystatechange();
     84             }
     85         });
     86     }
     87 }
     88 /* 现代浏览器需要通过DOMParser对象并通过parseFromString来转换XML文档为字符串 */
     89 function _fix_xml(){
     90     // ES5新特性.
     91     if(Object.defineProperty){
     92         Object.defineProperty(Node.prototype,"xml",{
     93             get:function(){
     94                 return (new XMLSerializer).serializeToString(this,"text/xml");
     95             }
     96         })
     97     }
     98     // 如下分支IE9开始不支持了.非W3C标准.
     99     //else if(Node.prototype.__defineGetter__){
    100     //    Node.prototype.__defineGetter__("xml",function(){
    101     //        return (new XMLSerializer).serializeToString(this,"text/xml");
    102     //    });
    103     //}
    104 }
    105 
    106 /* 测试 */
    107 window.onload=function(){
    108     var xml1=createXMLDOM();
    109     var xml2=createXMLDOM();
    110     xml2.onreadystatechange=function(){
    111         // 这里不能用this.因为在处理ActiveX对象可能出现问题.
    112         if(xml2.readyState==4){
    113             document.body.innerHTML+="load xml ok<br/>";
    114         }
    115     }
    116     xml2.loadXML("<xml><blog>xf_z1988</blog></xml>");
    117     var xml_str=xml2.xml.replace(/</g,"&lt;").replace(/>/g,"&gt;");
    118     document.body.innerHTML+=xml_str;
    119 };
    120 </script>
    121 </head>
    122 <body></body>
    123 </html>
  • 相关阅读:
    【译】深入理解G1的GC日志(一)
    【译】深入理解G1的GC日志(一)
    【译】深入理解G1的GC日志(一)
    Java 8 Time Api 使用指南-珍藏限量版
    颠覆微服务认知:深入思考微服务的七个主流观点
    函数式编程让你忘记设计模式
    使用Optional摆脱NPE的折磨
    使用Optional摆脱NPE的折磨
    使用Optional摆脱NPE的折磨
    面试官:优化代码中大量的if/else,你有什么方案?
  • 原文地址:https://www.cnblogs.com/xf_z1988/p/javascript_xml_loadxml_onreadystatechange_xml.html
Copyright © 2020-2023  润新知