瀏覽器中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,"<").replace(/>/g,">"); 118 document.body.innerHTML+=xml_str; 119 }; 120 </script> 121 </head> 122 <body></body> 123 </html>