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>

復制代碼

發佈留言