«
javascript之XML DOM对象

时间:2008-5-31    作者:Deri    分类: 分享


   <p>  javacript中对xml dom的支持,与其他任何特性一样面临着浏览器兼容问题。</p><p>  一 IE中的XML DOM</p><p>  1.微软通过ActiveX的MSXML库提供了支持,通过:</p><p>  var oXmlDom = new ActiveXObject("MSXML2.DOMDocument.5.0")得到一个XML DOM对象,这是在IE6中的,如果你的IE是更老版本的,可以使用下面的函数得到,如果你没有安装MSXML,将不能得到:</p><p><code>function createXMLDOM() {<br />    <br />      var arrSignatures = ["MSXML2.DOMDocument.5.0", "MSXML2.DOMDocument.4.0",<br />                 "MSXML2.DOMDocument.3.0", "MSXML2.DOMDocument",<br />                 "Microsoft.XmlDom"];<br />                <br />      for (var i=0; i < arrSignatures.length; i++) {<br />        try {<br />        <br />          var oXmlDom = new ActiveXObject(arrSignatures[i]);<br />          <br />          return oXmlDom;<br />        <br />        } catch (oError) {<br />          //ignore<br />        }<br />      }       <br />      <br />      throw new Error("你的系统没有安装MSXML");     <br />    }</code></p><p>  当然,如果你使用prototype库,可以使用Try.these函数。</p><p>  2.XML DOM对象可以通过load和loadXML方法载入xml文件或者字符串:</p><p>  oXmlDom.load("test.xml");</p>
<p> </p>

   <p>  oXmlDom.loadXML("<root></root>");然后这个oXmlDom就可以使用所有的DOM对象方法,比如documentElement.tagName,参见:</p><p>  《<a href="http://tech.ddvip.com/2008-01/120059915340607.html">javascript之DOM技术(一)》</a></p><p>  《<a href="http://tech.ddvip.com/2008-01/120059928240608.html">javascript之dom技术(二)》</a></p><p>  3.XML DOM默认是通过异步载入xml文件的,可以通过设置async值来选择是同步还是异步:</p><p>  oXmlDom.async=true;</p><p>  4.IE的XML DOM拥有一个readyState值用来表示载入文件的状态:</p><p>  0――准备载入</p><p>  1――正在载入</p><p>  2――载入完成</p><p>  3――载入完成并可用,但有一部分数据也许不可用</p><p>  4――完全载入,完全可用。</p><p>  相应的有一个onreadystatechange事件,当状态改变时发生,我们可以通过监听此事件来判断XML DOM对象的可用性</p><p><code>oXmlDom.onreadystatechange = function () {<br />        if (oXmlDom.readyState == 4) {<br />          alert("load test.xml done!");<br />          alert("Tag name of the root element is " + oXmlDom.documentElement.tagName);<br />          alert("The root element has this many children: " + oXmlDom.documentElement.childNodes.length);<br />  <br />        }<br />      };</code>5.IE的XML DOM对象有一个xml属性,用来返回xml文件的字符串形式,比如</p><p><code>oXmlDom.async=false;<br />oXmlDom.load("test.xml");<br />alert(oXmlDom.xml);<br />alert出:<root><child/><child/></root></code></p>
 <p> </p>

   <p>  6.IE,当载入的XML文件或者字符串解析错误时,将产生一个parseError对象,我们在下面的代码中演示此对象的属性:</p><p><code>      oXmlDom.async = false;<br />      oXmlDom.load("errors.xml");<br />      <br />      //0表示没有错误<br />      if (oXmlDom.parseError != 0) {<br />        var oError = oXmlDom.parseError;<br />      <br />        alert("An error occurred:<br />错误代码: "<br />           + oError.errorCode + "<br />"<br />           + "行数: " + oError.line + "<br />"<br />           + "列数: " + oError.linepos + "<br />"<br />           + "原因: " + oError.reason);<br />           <br />      }</code></p><p>  二.Mozilla的XML DOM对象</p><p>  1.XML DOM对象的创建,符合DOM标准的,通过document.implementation.createDocument()方法。比如:</p><p>  var oXmlDom=document.implementation.createDocument("","",null);</p><p>  这三个参数分别是文档命名空间、文档元素的标签名以及一个文档类型对象(总为null),比如:</p><p>  var oXmlDom=document.implementation.createDocument("http://www.rubyeye.net","root",null);</p><p>  这段代码创建了一个<a0:root xmlns="http://www.rubyeye.net"/>的XML DOM对象</p><p>  2.载入xml,Mozilla与IE不同的是只提供了一个load()方法用于载入xml文件,没有提供loadXML()方法用于载入XML字符串。同步载入XML文件的代码与IE相同:</p>
 <p> </p>

   <p><code>oXmlDom.async=false;<br />oXmlDom.load("test.xml");</code></p><p>  异步载入稍有不同,因为Mozilla并不支持readyState属性,并且没有onreadystatechange事件,它只有一个onload的事件,当载入完成时触发;或者说相当于IE的readyState属性等于4的状态。</p><p><code>oXmlDom.onload=function(){<br />alert("done");<br />}</code></p><p>  oXmlDom.load("test.xml");</p><p>  要将XML字符串解析为DOM对象,必须使用DOMParser对象:</p><p>  var oParser=new DOMParser();</p><p>  var oXmlDom=oParser.parseFromString("<root><child/></root>,"text/xml");</p><p>  两个参数:要解析的XML字符串以及字符串的内容类型(只能为text/xml或者application/xml)。</p><p>  不过我们可以实现自己的loadXML方法:</p><p><code> Document.prototype.loadXML = function (sXml) {<br />  <br />      var oParser = new DOMParser();<br />      var oXmlDom = oParser.parseFromString(sXml, "text/xml");<br />    <br />      //删除原文档内容<br />      while (this.firstChild) {<br />        this.removeChild(this.firstChild);<br />      }<br />      //导入新的文档内容<br />      for (var i=0; i < oXmlDom.childNodes.length; i++) {<br />        var oNewNode = this.importNode(oXmlDom.childNodes[i], true);<br />        this.appendChild(oNewNode);<br />      }<br />    <br />    };</code></p><p>  3.Mozilla没有提供IE的xml属性来返回XML文档内容,只能通过使用XMLSerializer对象:</p>
 <p> </p>

   <p>  var oSerializer=new XMLSerializer();</p><p>  var sXml=oSerializer.serializeToString(oXmlDom,"text/xml");同样两个参数:XML DOM对象以及转化成的文档类型。</p><p>  同样,我们也可以给Mozilla的XML DOM对象定义一个属性xml,通过defineGetter方法:</p><p><code>Node.prototype.__defineGetter__("xml",function(){<br />var oSerializer=new XMLSerializer();<br />var sXml=oSerializer.serializeToString(this,"text/xml");<br />});</code>以后就可以以IE的方式,oXmlDom.xml来获取XML文档内容。</p><p>  4。错误处理,同样与IE不同,Mozilla当解析错误时会返回一段代码,以标签<prasereoor>包括其中的代码解释了错误发生的原因以及位置等信息,我们只有通过正则表达式解析此段代码,提取错误信息。</p><p><code>   var reError = />([sS]*?)Location:([sS]*?)Line Number (d+), Column (d+):<sourcetext>([sS]*?)(?:-*^)/;<br />     <br />      //返回代码的标签名为parsererror,表示错误发生<br />      if (oXmlDom.documentElement.tagName == "parsererror") {<br />        reError.test(oXmlDom.xml);<br />        alert("An error occurred:<br />描述: "<br />          + RegExp.$1 + "<br />"<br />          + "文件名: " + RegExp.$2 + "<br />"<br />          + "行数: " + RegExp.$3 + "<br />"<br />          + "列数: " + RegExp.$4 + "<br />"<br />          + "原因: " + RegExp.$5);<br />      }</code></p>
 <p> </p>

   <p>  三,提供一个跨浏览器的XML DOM对象解决方案,来自于《javascript高级程序设计》</p><p><code>function XmlDom() {<br />  //通过对象/属性检测法,判断是IE来是Mozilla<br />  if (window.ActiveXObject) {<br />    var arrSignatures = ["MSXML2.DOMDocument.5.0", "MSXML2.DOMDocument.4.0",<br />               "MSXML2.DOMDocument.3.0", "MSXML2.DOMDocument",<br />               "Microsoft.XmlDom"];<br />            <br />    for (var i=0; i < arrSignatures.length; i++) {<br />      try {<br />    <br />        var oXmlDom = new ActiveXObject(arrSignatures[i]);<br />      <br />        return oXmlDom;<br />    <br />      } catch (oError) {<br />        //ignore<br />      }<br />    }     <br />  <br />    throw new Error("MSXML is not installed on your system.");<br />     <br />  //同上     <br />  } else if (document.implementation && document.implementation.createDocument) {<br />    <br />    var oXmlDom = document.implementation.createDocument("","",null);<br />  <br />    //创建Mozilla版本的parseError对象<br />    oXmlDom.parseError = {<br />      valueOf: function () { return this.errorCode; },<br />      toString: function () { return this.errorCode.toString() }<br />    };<br />    <br />    //初始化parseError对象<br />    oXmlDom.__initError__();<br />        <br />    <br />    oXmlDom.addEventListener("load", function () {<br />      this.__checkForErrors__();<br />      this.__changeReadyState__(4);<br />    }, false);<br />  <br />    return oXmlDom;    <br />    <br />  } else {<br />    throw new Error("Your browser doesn't support an XML DOM object.");<br />  }<br />}<br />  <br />//此处用到了该书中一个浏览器系统检测js文件,如果是Mozilla<br />if (isMoz) {<br />  <br />  Document.prototype.readyState = 0;<br />  Document.prototype.onreadystatechange = null;<br />  <br />  Document.prototype.__changeReadyState__ = function (iReadyState) {<br />    this.readyState = iReadyState;<br />  <br />    if (typeof this.onreadystatechange == "function") {<br />      this.onreadystatechange();<br />    }<br />  };<br />  //初始化parseError对象<br />  Document.prototype.__initError__ = function () {<br />    this.parseError.errorCode = 0;<br />    this.parseError.filepos = -1;<br />    this.parseError.line = -1;<br />    this.parseError.linepos = -1;<br />    this.parseError.reason = null;<br />    this.parseError.srcText = null;<br />    this.parseError.url = null;<br />  };<br />  <br />  Document.prototype.__checkForErrors__ = function () {<br />  <br />    if (this.documentElement.tagName == "parsererror") {<br />  <br />      var reError = />([sS]*?)Location:([sS]*?)Line Number (d+), Column (d+):<sourcetext>([sS]*?)(?:-*^)/;<br />  <br />      reError.test(this.xml);<br />      <br />      this.parseError.errorCode = -999999;<br />      this.parseError.reason = RegExp.$1;<br />      this.parseError.url = RegExp.$2;<br />      this.parseError.line = parseInt(RegExp.$3);<br />      this.parseError.linepos = parseInt(RegExp.$4);<br />      this.parseError.srcText = RegExp.$5;<br />    }<br />  };<br />  <br />   //定义Mozilla的loadXML方法 <br />  Document.prototype.loadXML = function (sXml) {<br />  <br />    this.__initError__();<br />  <br />    this.__changeReadyState__(1);<br />  <br />    var oParser = new DOMParser();<br />    var oXmlDom = oParser.parseFromString(sXml, "text/xml");<br />    while (this.firstChild) {<br />      this.removeChild(this.firstChild);<br />    }<br />  <br />    for (var i=0; i < oXmlDom.childNodes.length; i++) {<br />      var oNewNode = this.importNode(oXmlDom.childNodes[i], true);<br />      this.appendChild(oNewNode);<br />    }<br />    <br />    //载入后检查错误<br />    this.__checkForErrors__();<br />    <br />    //没有问题,设置readyState属性为4<br />    this.__changeReadyState__(4);<br />  <br />  };<br />  <br />  Document.prototype.__load__ = Document.prototype.load;<br />  <br />  Document.prototype.load = function (sURL) {<br />    this.__initError__();<br />    this.__changeReadyState__(1);<br />    this.__load__(sURL);<br />  };<br />  <br />  Node.prototype.__defineGetter__("xml", function () {<br />    var oSerializer = new XMLSerializer();<br />    return oSerializer.serializeToString(this, "text/xml");<br />  });<br />  <br />}</code></p>