javacript中對xml dom的支持,與其他任何特性一樣面臨著瀏覽器兼容問題。
一 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");
????});
}