《JavaScript高級程序設計》閱讀筆記(二十一):JavaScript中的XML
雖然XML和DOM已經變成Web開發的重要組成部分,但目前僅IE跟Mozilla支持客戶端的XML處理。
一、IE中的XML DOM支持
IE對XML的支持是基于ActiveX的MSXML庫。
1、DOM創建
對每個新版本的MSXML,都會創建出不同的XML DOM對象,所以盡量選擇新的XML DOM版本。
2、載入XML
載入XML分兩種,即:
載入XML字符串:loadXML(xml字符串)
載入xml文件:load(xml文件路徑)。默認情況下文件載入是異步的,如果要改為同步把asynce特性改為true即可。異步載入文件時要用到readyState和onreadystatechange事件處理函數。readyState共有五種可能的值:
0——DOM尚未初始化任何信息;
1——DOM正在載入數據;
2——DOM完成了數據載入;
3——DOM已經可用,不過某些部分可能還不能用;
4——DOM已經完全被載入,可以使用了。
3、獲取XML
微軟為每個節點增加了xml特性,所以獲取XML非常方便,見后面的示例。
4、解釋錯誤
可以用parseError來處理XML載入過程中出現的錯誤。
parseError特性實際上是包含以下特性的對象:
errorCode:錯誤類型數字代碼,沒有錯誤為0
filePos:錯誤發生在文件中的位置
line:遇到錯誤的行號
linepos:在遇到錯誤的那一行上的字符的位置
reason:對錯誤的一個解釋
srcText:造成錯誤的代碼
url:造成錯誤的文件的URL
5、示例:
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){ } } throw new Error("MSXML is not installed on your system"); } var oXmlDom=createXMLDOM(); //方式一:加載字符串 oXmlDom.loadXML("<root><child/></rot>"); //處理錯誤 if(oXmlDom.parseError != 0){ var oError=oXmlDom.parseError; alert("An Error occurred:\nError Code:" + oError.errorCode + "\nLine:" + oError.line + "\nLine Pos:" + oError.linepos + "\nReason:" + oError.reason); } else { var childNodes=oXmlDom.documentElement.childNodes; console.log(childNodes.length+" "+childNodes[0].xml);// 1 <child/> } //方式二:加載XML文件 oXmlDom.onreadystatechange = function(){ //文檔加載完畢 if(oXmlDom.readyState == 4){ if(oXmlDom.parseError != 0){ var oError=oXmlDom.parseError; alert("An Error occurred:\nError Code:" + oError.errorCode + "\nLine:" + oError.line + "\nLine Pos:" + oError.linepos + "\nReason:" + oError.reason); } else { var childNodes=oXmlDom.documentElement.childNodes; console.log(childNodes.length+" "+childNodes[0].xml);// 1 <child/> } } } oXmlDom.load("test.xml");
二、Mozilla中的XML DOM支持
1、創建DOM
DOM標準指出,document.implementation有個 createDocument() 方法:
var oXmlDom=document.implementation.createDocument("","",null);
其中,第一個參數為文檔的命名空間URL,文檔元素的標簽名,和文檔類型對象(總是為null,因為在Mozilla中還沒有支持)。
2、載入XML
Mozilla只支持一個載入XML的方法:load(文件名)。
同步或異步由async決定,默認為異步。
如果是XML字符串,要用DOMParser對象來轉換成DOM,用法如下:
var oParser = new DOMParser(); var oXmlDom = oParser.parseFromString("<root/>","text/xml");
parseFromString方法第一個參數為XML字符串,第二個參數為內容類型。可以是 "text/xml" 或 "application/xml"。
3、獲取XML
微軟提供的xml特性因為不是標準,所以Mozilla不支持,Mozilla提供了XMLSerializer對象:
var oSerializer = new XMLSerializer(); var sXml = oSerializer.serializeToString(oXmlDom,"text/xml");
在后面的例子中我們可以看到如何用defineGetter()方法來定義一個xml特性。
4、解析錯誤
在XML文件的解析過程中發生錯誤時,XML DOM會創建文檔來解釋這個錯誤。常常用正則來輸出錯誤信息:
var reError = />([\s\S]*?)Location:([\s\S]*?)Line Number (\d+),Column (\d+):<sourcetext>([\s\S]*?)(?:\-*\^)/; if(oXmlDom.documentElement.tagName == "parsererror"){ reError.test(oXmlDom.xml); alert("An error occurred:\nDescription: " + RegExp.$1 +"\n" + "File: " + RegExp.$2 + "\n" + "Line: " + RegExp.$3 + "\n" + "Line Pos: " + RegExp.$4 + "\n" + "Source: " + RegExp.$5); }
5、示例
var oXmlDom=document.implementation.createDocument("","<root>",null); oXmlDom.async = false; oXmlDom.onload = function(){ alert('Done'); } var reError = />([\s\S]*?)Location:([\s\S]*?)Line Number (\d+),Column (\d+):<sourcetext>([\s\S]*?)(?:\-*\^)/; if(oXmlDom.documentElement.tagName == "parsererror"){ reError.test(oXmlDom.xml); alert("An error occurred:\nDescription: " + RegExp.$1 +"\n" + "File: " + RegExp.$2 + "\n" + "Line: " + RegExp.$3 + "\n" + "Line Pos: " + RegExp.$4 + "\n" + "Source: " + RegExp.$5); } Node.prototype.__defineGetter__("xml", function () { var oSerializer = new XMLSerializer(); return oSerializer.serializeToString(this, "text/xml"); }); oXmlDom.load('test.xml'); alert(oXmldom.xml); var oNode = oXmlDom.documentElement.childNodes[1]; alert(oNode.xml);
三、通用接口
下面是兼容IE和FireFox的通用接口:
function XmlDom() { if (window.ActiveXObject) {//IE 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); oXmlDom.parseError = {valueOf:function () { return this.errorCode; }, toString:function () { return this.errorCode.toString(); }}; 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."); } } 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(); } }; 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; } }; 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__(); this.__changeReadyState__(4); }; Document.prototype.__load__ = Document.prototype.load; Document.prototype.load = function (sURL) { this.__initError__(); this.__changeReadyState__(1); this.__load__(sURL); }; Document.prototype.getReadyState = function () { return this._readyState_; }; Node.prototype.__defineGetter__("xml", function () { var oSerializer = new XMLSerializer(); return oSerializer.serializeToString(this, "text/xml"); }); }
四、其他瀏覽器
本書中沒有講到其他瀏覽器,如現在很火的Chrome,最新版的主流瀏覽器現在都已支持上面講到的Mozilla方式。如果不支持,可以用AJAX來讀取處理XML。

浙公網安備 33010602011771號