浏览器中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>