一 IE中的XML DOM
1.微軟通過ActiveX的MSXML庫提供了支持,通過:
- var oXMLDom = new ActiveXObject("MSXML2.DOMDocument.5.0")
得到一個XML DOM對象,這是在IE6中的,如果你的IE是更老版本的,可以使用下面的函數得到,如果你沒有安裝MSXML,將不能得到:
- function createXMLDOM() {
- var arrSignatures = ["MSXML2.DOMDocument.5.0", "MSXML2.DOMDocument.4.0",
- "MSXML2.DOMDocument.3.0", "MSXML2.DOMDocument",
- "Microsoft.XMLDom"];
- for (var i=0; i < arrSignatures.length; i++) {
- try {
- var oXMLDom = new ActiveXObject(arrSignatures[i]);
- return oXMLDom;
- } catch (oError) {
- //ignore
- }
- }
- throw new Error("你的系統沒有安裝MSXML");
- }
當然,如果你使用prototype庫,可以使用Try.these函數。
2.XML DOM對象可以通過load和loadXML方法載入XML文件或者字符串:
- oXMLDom.load("test.XML");
- oXmlDom.loadXML("<root></root>");
然後這個oXMLDom就可以使用所有的DOM對象方法,比如documentElement.tagName,參見:
《Javascript之DOM技術(一)》
《Javascript之dom技術(二)》
3.XML DOM默認是通過異步載入XML文件的,可以通過設置async值來選擇是同步還是異步:
- oXMLDom.async=true;
4.IE的XML DOM擁有一個readyState值用來表示載入文件的狀態:
0——准備載入
1——正在載入
2——載入完成
3——載入完成並可用,但有一部分數據也許不可用
4——完全載入,完全可用。
相應的有一個onreadystatechange事件,當狀態改變時發生,我們可以通過監聽此事件來判斷XML DOM對象的可用性
- oXMLDom.onreadystatechange = function () {
- if (oXMLDom.readyState == 4) {
- alert("load test.XML done!");
- alert("Tag name of the root element is " + oXMLDom.documentElement.tagName);
- alert("The root element has this many children: " + oXMLDom.documentElement.childNodes.length);
- }
- };
5.IE的XML DOM對象有一個xml屬性,用來返回XML文件的字符串形式,比如
- oXMLDom.async=false;
- oXMLDom.load("test.XML");
- alert(oXmlDom.XML);
alert出:<root><child/><child/></root>
6.IE,當載入的XML文件或者字符串解析錯誤時,將產生一個parseError對象,我們在下面的代碼中演示此對象的屬性:
- oXMLDom.async = false;
- oXMLDom.load("errors.XML");
- //0表示沒有錯誤
- if (oXMLDom.parseError != 0) {
- var oError = oXMLDom.parseError;
- alert("An error occurred:\n錯誤代碼: "
- + oError.errorCode + "\n"
- + "行數: " + oError.line + "\n"
- + "列數: " + oError.linepos + "\n"
- + "原因: " + oError.reason);
- }
二.Mozilla的XML DOM對象
1.XML DOM對象的創建,符合DOM標准的,通過document.implementation.createDocument()方法。比如:
- var oXMLDom=document.implementation.createDocument("","",null);
這三個參數分別是文檔命名空間、文檔元素的標簽名以及一個文檔類型對象(總為null),比如:
- var oXMLDom=document.implementation.createDocument("http://www.rubyeye.Net","root",null);
這段代碼創建了一個<a0:root XMLns="http://www.rubyeye.Net"/>的XML DOM對象
2.載入xml,Mozilla與IE不同的是只提供了一個load()方法用於載入xml文件,沒有提供loadXML()方法用於載入XML字符串。同步載入XML文件的代碼與IE相同:
- oXMLDom.async=false;
- oXMLDom.load("test.XML");
異步載入稍有不同,因為Mozilla並不支持readyState屬性,並且沒有onreadystatechange事件,它只有一個onload的事件,當載入完成時觸發;或者說相當於IE的readyState屬性等於4的狀態。
- oXMLDom.onload=function(){
- alert("done");
- }
- oXMLDom.load("test.XML");
要將XML字符串解析為DOM對象,必須使用DOMParser對象:
- var oParser=new DOMParser();
- var oXMLDom=oParser.parseFromString("<root><child/></root>,"text/XML");
兩個參數:要解析的XML字符串以及字符串的內容類型(只能為text/xml或者application/XML)。
不過我們可以實現自己的loadXML方法:
- Document.prototype.loadXML = function (sXML) {
- var oParser = new DOMParser();
- var oXmlDom = oParser.parseFromString(sXML, "text/XML");
- //刪除原文檔內容
- while (this.firstChild) {
- this.removeChild(this.firstChild);
- }
- //導入新的文檔內容
- for (var i=0; i < oXMLDom.childNodes.length; i++) {
- var oNewNode = this.importNode(oXMLDom.childNodes[i], true);
- this.appendChild(oNewNode);
- }
- };
3.Mozilla沒有提供IE的xml屬性來返回XML文檔內容,只能通過使用XMLSerializer對象:
- var oSerializer=new XMLSerializer();
- var sXml=oSerializer.serializeToString(oXMLDom,"text/XML");
同樣兩個參數:XML DOM對象以及轉化成的文檔類型。
同樣,我們也可以給Mozilla的XML DOM對象定義一個屬性XML,通過defineGetter方法:
- Node.prototype.__defineGetter__("XML",function(){
- var oSerializer=new XMLSerializer();
- var sXML=oSerializer.serializeToString(this,"text/XML");
- });
以後就可以以IE的方式,oXmlDom.xml來獲取XML文檔內容。
4。錯誤處理,同樣與IE不同,Mozilla當解析錯誤時會返回一段代碼,以標簽<prasereoor>包括其中的代碼解釋了錯誤發生的原因以及位置等信息,我們只有通過正則表達式解析此段代碼,提取錯誤信息。
- var reError = />([\s\S]*?)Location:([\s\S]*?)Line Number (\d+), Column (\d+):<sourcetext>([\s\S]*?)(?:\-*\^)/;
- //返回代碼的標簽名為parsererror,表示錯誤發生
- if (oXMLDom.documentElement.tagName == "parsererror") {
- reError.test(oXmlDom.XML);
- alert("An error occurred:\n描述: "
- + RegExp.$1 + "\n"
- + "文件名: " + RegExp.$2 + "\n"
- + "行數: " + RegExp.$3 + "\n"
- + "列數: " + RegExp.$4 + "\n"
- + "原因: " + RegExp.$5);
- }
三,提供一個跨浏覽器的XML DOM對象解決方案,來自於《Javascript高級程序設計》
- function XMLDom() {
- //通過對象/屬性檢測法,判斷是IE來是Mozilla
- if (window.ActiveXObject) {
- var arrSignatures = ["MSXML2.DOMDocument.5.0", "MSXML2.DOMDocument.4.0",
- "MSXML2.DOMDocument.3.0", "MSXML2.DOMDocument",
- "Microsoft.XMLDom"];
- for (var i=0; i < arrSignatures.length; i++) {
- try {
- var oXMLDom = new ActiveXObject(arrSignatures[i]);
- return oXMLDom;
- } catch (oError) {
- //ignore
- }
- }
- throw new Error("MSXML is not installed on your system.");
- //同上
- } else if (document.implementation && document.implementation.createDocument) {
- var oXMLDom = document.implementation.createDocument("","",null);
- //創建Mozilla版本的parseError對象
- oXMLDom.parseError = {
- valueOf: function () { return this.errorCode; },
- toString: function () { return this.errorCode.toString() }
- };
- //初始化parseError對象
- oXMLDom.__initError__();
- oXMLDom.addEventListener("load", function () {
- this.__checkForErrors__();
- this.__changeReadyState__(4);
- }, false);
- return oXMLDom;
- } else {
- throw new Error("Your browser doesn't support an XML DOM object.");
- }
- }
- //此處用到了該書中一個浏覽器系統檢測JS文件,如果是Mozilla
- if (isMoz) {
- Document.prototype.readyState = 0;
- Document.prototype.onreadystatechange = null;
- Document.prototype.__changeReadyState__ = function (iReadyState) {
- this.readyState = iReadyState;
- if (typeof this.onreadystatechange == "function") {
- this.onreadystatechange();
- }
- };
- //初始化parseError對象
- Document.prototype.__initError__ = function () {
- this.parseError.errorCode = 0;
- this.parseError.filepos = -1;
- this.parseError.line = -1;
- this.parseError.linepos = -1;
- this.parseError.reason = null;
- this.parseError.srcText = null;
- this.parseError.url = null;
- };
- Document.prototype.__checkForErrors__ = function () {
- if (this.documentElement.tagName == "parsererror") {
- var reError = />([\s\S]*?)Location:([\s\S]*?)Line Number (\d+), Column (\d+):<sourcetext>([\s\S]*?)(?:\-*\^)/;
- reError.test(this.XML);
- this.parseError.errorCode = -999999;
- this.parseError.reason = RegExp.$1;
- this.parseError.url = RegExp.$2;
- this.parseError.line = parseInt(RegExp.$3);
- this.parseError.linepos = parseInt(RegExp.$4);
- this.parseError.srcText = RegExp.$5;
- }
- };
- //定義Mozilla的loadXML方法
- Document.prototype.loadXML = function (sXML) {
- this.__initError__();
- this.__changeReadyState__(1);
- var oParser = new DOMParser();
- var oXmlDom = oParser.parseFromString(sXML, "text/XML");
- while (this.firstChild) {
- this.removeChild(this.firstChild);
- }
- for (var i=0; i < oXMLDom.childNodes.length; i++) {
- var oNewNode = this.importNode(oXMLDom.childNodes[i], true);
- this.appendChild(oNewNode);
- }
- //載入後檢查錯誤
- this.__checkForErrors__();
- //沒有問題,設置readyState屬性為4
- this.__changeReadyState__(4);
- };
- Document.prototype.__load__ = Document.prototype.load;
- Document.prototype.load = function (sURL) {
- this.__initError__();
- this.__changeReadyState__(1);
- this.__load__(sURL);
- };
- Node.prototype.__defineGetter__("XML", function () {
- var oSerializer = new XMLSerializer();
- return oSerializer.serializeToString(this, "text/XML");
- });
- }