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>包括其中的代碼解釋了錯誤發生的原因以及位置等資訊,我們只有通過Regex解析此段代碼,提取錯誤資訊。
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");