瀏覽器中的XML


瀏覽器中的XML

打開XML

首先,直接從瀏覽器中打開XML文件,瀏覽器會對其進行格式良好性檢查,如果不符合XML語法規范則顯示出錯,如果格式良好,再檢查是否包含樣式表(CSS或XSL),如果包含樣式表,則用樣式表格式化XML文檔然后顯示,如果沒有,則顯示經過格式化的XML源碼(不同瀏覽器顯示方式不一樣).注意,瀏覽器只對XML進行格式良好性檢查,而不對其進行有效性檢查!如何在XML文檔中引入樣式表?示例:

	<?xml version="1.0" standalone="no"?>
	<?xml-stylesheet type="text/css" href="test.css"?>

如果是使用XSL,只需將上面的type屬性值改成text/xsl即可!

XMLHttpRequest對象的responseXML屬性

XMLHttpRequest對象的responseXML屬性用來獲取從服務器端返回的XML文件,如果沒有則為null.注意,只有在服務器環境下,請求一個以.xml為后綴的文件返回的才會是一個XML DOM,在本地請求一個XML文件,返回的仍是文本文件.如果要使用服務器腳本生成字符串,要返回XML,必須加上一些頭信息

	//JS Code
	var xhr = XHR();//XHR為之前所寫的可以跨瀏覽器創建XMLHttpRequest對象的函數
	xhr.open("get","test.php",true);
	xhr.onreadystatechange = function () {
		if (xhr.readyState==4 && xhr.status == 200) {
			//輸出root
			alert(xhr.responseXML.documentElement.nodeName);//可以使用DOM 2 Core的一些屬性和方法
		}
	};
	xhr.send(null);
	//PHP Code
	header("Content-Type:text/xml");//發送MIME信息
	echo  <<<XML
		<?xml version="1.0" encoding="gbk"?>
		<root />
	XML;

更簡單的方法:直接加載XML文件

瀏覽器也提供了直接加載XML文件的方法,但也僅僅火狐與Windows平台上的IE支持而已.同樣,兩者之間的實現也有很大的差別的!

IE中的XML DOM

微軟在JavaScript中引入了用於創建ActiveX對象的ActiveXObject類。ActiveXObject的構造函數只有一個參數——要進行實例化的ActiveX對象的字符串代號。例如,XML DOM對象的第一個版本稱為Microsoft.XmlDom。所以,要創建這個對象的實例,使用以下代碼:

	var xmlDom = new ActiveXObject("Microsoft.XmlDom");

IE中的XML DOM支持的最新版本是5.0,IE中存在以下版本的XML DOM實現:

  • Microsoft.XmlDom(最原始的)
  • MSXML2.DOMDocument
  • MSXML2.DOMDocument.3.0
  • MSXML2.DOMDocument.4.0
  • MSXML2.DOMDocument.5.0

自然地,只要可能,大家都會選擇最新的XML DOM的版本,因為新版會提高速度,添加一些新的功能如驗證等。但是,如果嘗試創建不存在於客戶端機器上的ActiveX對象,IE就會拋出錯誤並停止所有執行。所以,為確保使用了正確的XML DOM版本,也為避免任何其他錯誤,我們可以創建一個函數來測試每個XML DOM字符串,出現錯誤即捕獲:

	function XMLDOM() {
		var xmlDomVers = [
		"Microsoft.XmlDom",
		"MSXML2.DOMDocument",
		"MSXML2.DOMDocument.3.0",
		"MSXML2.DOMDocument.4.0",
		"MSXML2.DOMDocument.5.0"
		];
		for (var i=xmlDomVers.length-1;i>=0;i--) {
			try {
				var xmlDom = new ActiveXObject(xmlDomVers[i]);
				return xmlDom;
			} catch(e) {continue;}
			
		}
	}

接下來就是載入XML. 微軟的XML DOM有兩種載入XML的方法:loadXML()和load()。loadXML()方法可直接向XML DOM輸入XML字符串.load()方法用於從服務器上載入XML文件。不過,load()方法只可以載入與包含JavaScript的頁面存儲於同一服務器上的文件,也就是說,不可以通過其他人的服務器載入XML文件。 load方法還有兩種載入文件的模式:同步和異步。以同步模式載入文件時,JavaScript代碼會等待文件完全載入后才繼續執行代碼;而以異步模式載入時,不會等待,可以使用事件處理函數來判斷文件是否完全載入了。默認情況下,文件按照異步模式載入。要進行同步載入,只需設置async特性為false:

	//Only For IE
	var xmlDom = XMLDOM();
	xmlDom.loadXML("<root />");
	alert(xmlDom.documentElement.nodeName);
	var xml = XMLDOM();
	xml.async = false;//同步載入
	xml.load("test.xml");
	alert(xml.documentElement.firstChild.nodeValue);
	//同步加載時需要使用readystatechange事件監聽
	var xml2 = XMLDOM();
	xml2.async=true;//可以不指定,默認是異步載入的
	xml2.onreadystatechange = function () {//必須在調用load方法前分配此事件處理函數
		if (xml2.readyState==4) {//readyState的含義和XHR對象是一樣的
			//注意這里沒有使用this,因為IE下的ActiveXObject很特殊,使用this會出錯
			alert(xml2.xml);//與innerHTML屬性類似,IE中的xml屬性返回XML字符串形式的源碼
			//但注意,IE中的XMLDOM對象的xml屬性是只讀的
		}
	};
	xml2.load("test.xml");

在嘗試將XML載入到XML DOM對象中時,無論使用loadXML()方法還是load()方法,都有可能出現XML格式不正確的情況。為解決這個問題,微軟的XML DOM的parseError的特性包含了關於解析XML代碼時所遇到的問題的所有信息。

parseError特性實際上是包含以下特性的對象:

  • errorCode——表示所發生的錯誤類型的數字代號(當沒有錯誤時為0)
  • filePos——錯誤發生在文件中的位置
  • line——遇到錯誤的行號
  • linepos——在遇到錯誤的那一行上的字符的位置
  • reason——對錯誤的一個解釋
  • srcText——造成錯誤的代碼
  • url——造成錯誤的文件的URL(如果可用)

當直接對parseError自身取值,它會返回errorCode的值,也就是說可以這樣進行檢查

	if (xmlDom.parseError===0) {
		alert("沒有出錯!");
	} else {
		var er = xmlDom.parseError;
		alert("XML解析出錯!錯誤信息如下:\n\
		錯誤代號:"+er.errorCode+"\n\
		文件:"+er.filePos+"\n\
		行:"++er.line+"\n\
		字符:"+er.linepos+"\n\
		相關信息:"+er.reason+"\n\");
	}

Mozilla中的XML DOM

與Mozilla其他方面一樣,它提供的XML DOM版本要比IE的更加標准。 Mozilla中的XML DOM實際上是它的JavaScript實現,也就是說它不僅與瀏覽器一起衍化,同時它能可靠地在Mozilla支持的所有平台上使用。因此與不能在Macintosh上使用XML DOM的IE不同,Mozilla的支持跨越了平台的界限。另外,Mozilla的XML DOM實現了支持DOM Level 2 的功能,而微軟的,僅支持DOM Level 1。

DOM標准指出,document.implementation對象有個可用的createDocument()方法。Mozilla嚴格遵循了這個標准,可以這樣創建XML DOM:

	var xmlDom = document.implementation.createDocument("","",null);

createDocument()的三個參數分別是文檔的命名空間URL,文檔元素的標簽名以及一個文檔類型對象(總是為null,因為在Mozilla中還沒有對文檔類型對象的支持)。前面這行代碼創建一個空的XML DOM。要創建包含一個文檔元素的XML DOM,只需將標簽名作為第二個參數:

	var xmlDom = document.implementation.createDocument("","root",null);

這行代碼創建了代表XML代碼<root/>的XML DOM。如果在第一個參數中指定了命名空間URL,可進一步定義文檔元素:

	var xmlDom = document.implementation.createDocument("http://www.x-do.org","root",null);

這行代碼創建了表示<root xmlns="http://www.x-do.org"/>的XML DOM

與微軟的XML DOM不同,Mozilla只支持一個載入數據的方法:load()。Mozilla中的load()方法和IE中的load()工作方式一樣。只要指定要載入的XML文件,以及同步還是異步(默認)載入。如果同步載入XML文件,代碼基本上IE差不多:

	var xmlDom = document.implementation.createDocument("","root",null);
	xmlDom.async = false;//同步載入
	xmlDom.load("test.xml");

與IE不同的是,同步載入時,並沒有readychange事件,而只有load事件,並且只有加載完畢一種狀態!

	var xmlDom = document.implementation.createDocument("","root",null);
	xmlDom.async = true;//異步載入
	xmlDom.onload = function () {
		alert(this.documentElement.childNodes.item(0).tagName);
		//對於JS,訪問節點列表既可以用item方法,又可用數字下標,而其它語言則不一定能使用下標
	};
	xmlDom.load("test.xml");

另外,麻煩的是,Mozilla的XML DOM不支持loadXML()方法。要將XML字符串解析為DOM,必須使用DOMParser對象,使用其parseFromString方法傳入XML字符串表現形式:

	var xmlParser = new DOMParser();
	var xmlDom = xmlParser.parseFromString("<root />","text/xml");//該方法返回一個XML DOM對象
	//第二個參數text/xml也可以是application/xml,兩者都用來解析XML
	//還可以是application/xhtml+xml,用來解析XHTML,只能用這三種MIME

與直接解析XML字符串相對應的獲取XML字符串的方法,IE中XML DOM對象具有只讀的xml屬性,而Mozilla 則沒有相對應的屬性,但是,Mozilla提供了可以用於同樣的目的的XMLSerializer對象:

	var serializer= new XMLSerializer();
	var xmlStr = serializer.serializeToString(xmlDom,"text/xml");
	//xmlDom為一個XML DOM節點對象
	//而text/xml也可為application/xml

對於XML 解析錯誤,Mozilla的實現方式非常麻煩,它不像IE那樣提供一個對象來表示錯誤,而是將錯誤信息作為一個XML文檔返回,要獲取具體的錯誤信息,還必須用解析其中的字符串!

	var xmlParser = new DOMParser();
	var xmlDom = xmlParser.parseFromString("<root><child></root>","text/xml");
	alert(xmlDom.documentElement.nodeName);//將返回parsererror,因為文檔解析出錯時
	var serializer = new XMLSerializer();
	var str = serializer.serializeToString(xmlDom,"text/xml");
	alert(str);//將輸出類似下面內容
	<parsererror xmlns="http://www.mozilla.org/newlayout/xml/parsererror.xml">
	XML解析錯誤:不符合的記號.預期:&lt;/child&gt;。 
	位置:file:///E:/XML/test.html 
	行:1,列:16:<sourcetext>&lt;root&gt;&lt;child&gt;&lt;/root&gt;
	---------------^</sourcetext></parsererror>

而從其中抽取出諸如行號這些錯誤信息,只好使用正則表達式了!但是由於瀏覽器的語言設置不同,使用正則表達式也是困難重重的! 可以看到,雖然Mozilla對XML DOM的實現更標准,但是使用起來是非常不方便的!

跨瀏覽器的XML DOM構造函數

說它跨瀏覽器,其實也僅僅是兼容Mozilla與Windows上的IE而已,而對於其它瀏覽器,則可以降級,考慮使用XHR的responseXML,雖然XHR對象該屬性沒有提供什么高級的方便的方法,但用於讀取XML已經足夠了!

if (document.implementation && document.implementation.createDocument) {
	//W3C
	var getXMLDOM=function () {//獲取一個XMLDOM對象
		return document.implementation.createDocument("","",null);
	},
	loadXMLFile=function (xmlDom,url,callback) {
		if (xmlDom.async===true) {
			xmlDom.onload=function () {
				if (xmlDom.documentElement.nodeName=="parsererror") {
					throw new Error("XML Parse Error:"+xmlDom.documentElement.firstChild.nodeValue);
				} else {
					callback.call(xmlDom);
				}
			};
		}
		xmlDom.load(url);
		return xmlDom;
	},
	loadXMLString=function (xmlDom,s) {
		var p = new DOMParser();
		var newDom=p.parseFromString(s,"text/xml");
		if (newDom.documentElement.nodeName=="parsererror") {
			throw new Error("XML Parse Error:"+newDom.documentElement.firstChild.nodeValue);
		}
		while (xmlDom.firstChild) {
			xmlDom.removeChild(xmlDom.firstChild);
		}
		for (var i=0,n;i<newDom.childNodes.length;i++) {
			n=xmlDom.importNode(newDom.childNodes[i],true);
			//importNode用於把其它文檔中的節點導入到當前文檔中
			//true參數同時導入子節點
			xmlDom.appendChild(n);
		}
		return xmlDom;
	},
	getXML=function (xmlNode) {
		var s= new XMLSerializer();
		return s.serializeToString(xmlNode,"text/xml");
	};
} else if (window.ActiveXObject) {
	//IE
	var getXMLDOM=function () {
		return new ActiveXObject("Microsoft.XmlDom");
	},loadXMLFile=function (xmlDom,url,callback) {
		xmlDom.onreadystatechange=function () {
			if (xmlDom.readyState===4) {
				if (xmlDom.parseError.errorCode===0) {
					callback.call(xmlDom);
				} else {
					throw new Error("XML Parse Error:"+xmlDom.parseError.reason);
				}
			}
		};
		xmlDom.load(url);
		return xmlDom;
	},loadXMLString=function (xmlDom,s) {
		xmlDom.loadXML(s);
		if (xmlDom.parseError.errorCode!==0) {
			throw new Error("XML Parse Error:"+xmlDom.parseError.reason);
		}
		return xmlDom;
	},
	getXML=function (xmlNode) {
		return xmlNode.xml;
	};
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM