不一樣瀏覽器對XML的解析問題(解決了多天困擾的問題)

[轉自]http://book.51cto.com/art/200806/75667.htm
 
第11章  Ajax標準通訊載體——XML語言
XML語言能夠有複雜的層次性結構,所以它能夠表示任意複雜的數據信息。同時XML是用純文本編寫的,便於人工閱讀和修改。在Ajax中,XML起着很重要的做用,本章將集中講解XML的相關知識。
11.1  XML概述
XML是Extensible Markup Language(取Extensible的X)的縮寫,便可擴展標記語言。它是W3C提出的一種用來描述數據的標準語言。它的通性使開發人員無需爲每一個應用程序都單獨設計一種數據表示,這給不一樣類型程序間的數據通訊帶來了很大的方便。好比Web服務通訊中的SOAP協議使用的就是XML語言,網絡上處處可見的RSS也是基於XML的。
11.1.1  一個簡單的XML實例
從某種程度上說,XML與HTML的語法至關相似,它們都是由文本以及包含文本的標記組成的。下面是一段簡單的HTML代碼,其中<u>和<i>標記分別表示下劃線顯示和斜體顯示效果,代碼以下:
<dl>
<dt><u>標題</u></dt>
<dd><i>條目1</i></dd>
<dd><i>條目2</i></dd>
<dd><i>條目3</i></dd>
</dl>
運行這段代碼的效果如圖11.1所示。
下面是一段內容相似的XML代碼:
<?xml version="1.0" encoding="GB2312"?>
<items>
<title>標題</title>
<item>條目1</item>
<item>條目2</item>
<item>條目3</item>
</items>
運行這段程序的效果如圖11.2所示。
對比以上兩段代碼,能夠發現幾個不一樣點。一是HTML中的標記都是特定的,每一個標記都有特定含義;而XML中的標記則徹底能夠由用戶本身定義。二是HTML的標記主要用於說明數據的顯示方式,好比下劃線、斜體、列表等;而XML只關心數據的內容,不關心數據如何顯示。
提示:事實上,W3C規定的另一個標準XSLT能夠爲XML指定顯示方式。
11.1.2  XML的基本概念
按照W3C的DOM模型,XML中的基本單位稱爲結點(Node),結點能夠有不少種類型,好比文檔(Document)、元素(Element)、屬性(Attribute)、文本(Text)等。
文檔結點是整個文檔最上層的結點,即根結點;元素結點能夠包含子結點,子結點能夠是屬性、文本甚至一個元素,即元素是能夠嵌套的。好比上面的例子中,「<title>標題</title>」是一個元素,整個「<items>……</items>」也是一個元素。其中title這個元素的內容「標題」就是一個文本結點,它在DOM模型中做爲title的子結點出現。整個XML文檔就造成了一個結點樹的結構。
而元素結點的標識是由標記(Tag)來完成的。XML中的標記是由小於號(<)開始,以大於號(>)結束。對於標記內容來講,若以斜槓(/)開頭,則認爲這是一個結束標記,表示一個元素的結束。不然這個標記就是一個開始標記,表示一個元素的開始。同時,在標記內也能夠附加一些屬性(Attribute),代碼爲:
<item name="itemname"></item>
這裏,爲item標記附加了一個name屬性,其值爲itemname。
注意:有些標記不包含任何內容,能夠直接在開始標記的結束符號(大於號)前加一個斜槓表示該標記的結束,如上面屬性的例子能夠寫爲:<item name="itemname"/>
在編寫XML的時候,須要特別注意如下幾個問題。
• XML標記是區別大小寫的,這與HTML不一樣;
• XML的屬性值必定要加引號(單引或雙引),而HTML中能夠忽略;
• XML中的全部標記都要「善始善終」,而HTML中的某些標記能夠沒有結束標記,如<br>、<img>;
• 「<![CDATA[」和「]]>」能夠用來包含有特殊字符(如大於號小於號)的文本,如<![CDATA[<item>text</item>]]>在XML就表示<item>text</item>這一段文本(注意:這裏的item由於被CDATA包含,已經不是一個標記了)。
11.1.3  XML在Ajax中的做用
XML的優點在於其通用性,和較強的表達能力,所以用XML做爲數據交換的一個標準格式無疑具備必定的吸引力。Ajax中客戶端與服務器端之間的通訊也能夠採用這種辦法。
實際上,在Ajax最初的定義中,XML是做爲一個客戶端與服務器端的通訊載體出現的。例如能夠將客戶端對服務器端的請求用XML包裝起來,也能夠將客戶端提交的一個表單內容轉化成一個XML片斷傳給服務器端進行處理。下面的XML片斷能夠表明一個註冊表單提交的內容,代碼以下:
<id>Richard</id>
<password>pass123</password>
<sex>男</sex>
<email>[email]richard@hotmail.com[/email]</email>
<address>南京大學鼓樓校區</address>
在Ajax中使用XML的另外一個緣由是,它能夠進一步下降客戶端和服務器端的耦合性。因爲XML的中立性,客戶端和服務器端使用的開發語言、平臺等一些細節都有自由選擇的空間,這與客戶端服務器架構的理念是一致的,即客戶端和服務器端應當相對獨立。
11.2  使用Javascript操做XML
11.2.1  MSXML介紹
在IE中,微軟提供了MSXML控件來支持XML操做。每一個系統安裝的MSXML版本都有可能不一樣,所以在編寫程序的時候要注意版本的肯定。目前MSXML從舊到新有如下幾個版本。
• Microsoft.XmlDom (最初的版本)
• MSXML2.DOMDocument
• MSXML2.DOMDocument.3.0
• MSXML2.DOMDocument.4.0
• MSXML2.DOMDocument.5.0
下面的函數用來獲取一個系統中可用的最新版本的DomDocument對象,若都不存在,則返回空,代碼以下:
function createDomDoc()
{
var signatures=["Msxml2.DOMDocument.5.0",
"Msxml2.DOMDocument.4.0",
"Msxml2.DOMDocument.3.0",
"Msxml2.DOMDocument",
"Microsoft.XmlDom"];
for(var i=0;i<signatures.length;i++)
{
try{
var domDoc = new ActiveXObject(signatures[i]);
return domDoc;
} catch(e) {
//忽略錯誤,繼續循環嘗試下一個版本
}
}
return null;
}
11.2.2  在IE瀏覽器中建立XML片斷
下面介紹如何經過DomDocument對象建立一個XML片斷,以11.1.3節中的XML片斷爲例。下面是代碼,返回的則是XML文本。
function createXml(doc)
{
var root = doc.createElement("items");
var title = doc.createElement("title");
title.text = '標題';
root.appendChild(title);    //添加title子結點
for(var i=0;i<3;i++)
{
var item = doc.createElement("item");
item.text = '條目'+i;
root.appendChild(item);   //添加item子結點
}
doc.appendChild(root);    //設置root結點
return doc.xml;
}
在這段代碼中,createElement方法用來創建一個新的元素結點,參數是這個結點標記的名稱。結點的text屬性能夠用來設置其內容(嚴格說,就是設置其文本子結點的內容)。
appendChild方法能夠在某個元素結點下添加子結點。在建立XML片斷的時候,須要使用該方法將構建好的XML附加到DomDocument對象上。XML屬性則能夠將DomDocument序列化,使其成爲一段文本。
在程序中加入下列執行代碼:
var domDoc = createDomDoc();
if(domDoc!=null)
{
var xml=createXml(domDoc);
alert(xml);
}
else
{
alert('未安裝MSXML控件');
}
運行結果如圖11.3所示。
圖11.3  經過XML DOM對象建立的XML文本
11.2.3  在IE瀏覽器中解析XML文本
下面介紹如何經過DomDocument對象來解析已有的XML文本。在IE中有2種導入XML文本的辦法。一種是經過load方法,其語法代碼以下。
domDoc.load("test.xml"); //導入test.xml文件中的內容
該方法只能導入JavaScript所在的本地文件,而不支持遠程導入。
第二種方法是經過loadXML方法直接導入,代碼是:
xml = " ";
domDoc.loadXML(xml); //直接解析xml中包含的XML文本
另外,因爲解析XML有時會花費較長的時間,MSXML還提供了異步機制,代碼以下:
domDoc.async = true; //異步調用
domDoc.onreadystatechange = function ()  //觸發函數
{
if(domDoc.readyState==4) {
doc = domDoc;
document.write("
");
var root = doc.documentElement;
document.write("
"+root.childNodes.item(0).text+"");
for(var i=1;i
{
node = root.childNodes.item(i);
document.write("
"+node.text+"");
}
document.write("
");
}
};
domDoc.loadXML(xml);
經過這段代碼能夠看出:設置DomDocument的async屬性能夠進行異步解析;childNodes屬性含有一個包含全部子結點的列表,能夠經過childNodes.item(i)來獲取索引值爲i的子結點;經過childNodes的length屬性能夠得到子結點的個數;結點的text屬性則能夠用來獲取某個元素結點的內容(或者說是其文本子結點的內容)。
另外,觸發函數中的readyState取值有其特定的含義。
• 1:表示正在載入,還沒開始解析;
• 2:表示數據已經載入完畢,開始解析,可是DOM仍不可用;
• 3:表示一些數據已經解析完成,DOM已經可使用,但還不完整,只包含已解析部分的數據。另外,此時的DOM是隻讀的;
• 4:表示數據解析已經所有完成,DOM已經能夠正常使用。
運行這段代碼,將會獲得如圖11.4所示的效果。
經過運行的結果能夠看出,觸發函數生成的實際上就是本章最開始給出的HTML代碼。
11.2.4  使用Mozilla瀏覽器支持的DOM模型建立XML片斷
在基於Mozilla的瀏覽器中(如Mozilla、Firefox、Netscape 6+等),對XML操做的支持是集成在瀏覽器內部的,這與IE瀏覽器使用外部控件的方式不一樣。
Mozilla瀏覽器的DOM模型對XML的操做方式也與IE瀏覽器有所不一樣,IE瀏覽器中的XML操做均集成在DomDocument對象中,而Mozilla瀏覽器中對XML的操做主要能夠分爲3個對象。
• Document對象:主要存放XML的數據及其結構;
• XMLSerializer對象:負責Document對象的序列化;
• DOMParser對象:負責解析XML文本。
建立一個XML片斷,代碼以下:
function createXml(doc)
{
var root = doc.createElement("items");
var title = doc.createElement("title");
title.textContent = '標題'; //注意Mozilla瀏覽器中使用的是textContent屬性
root.appendChild(title);
for(var i=0;i<3;i++)
{
var item = doc.createElement("item");
item.textContent = '條目'+i;
root.appendChild(item);
}
doc.appendChild(root);
var serializer = new XMLSerializer(); //序列化方式也與IE瀏覽器中不一樣
var xml = serializer.serializeToString(doc);
return xml;
}
var domDoc = document.implementation.createDocument("", "", null); //建立Document對象
var xml=createXml(domDoc);
alert(xml);
Document對象的建立是經過createDocument來進行的,createDocument是DOM模型規定的一個標準方法,它的原型代碼以下:
Document createDocument(in DOMString namespaceURI,
in DOMString qualifiedName,
in DocumentType doctype) raises(DOMException);
其中namespaceURI爲文檔的名字空間,qualifiedName是文檔的限定名,docType則是文檔的類型。通常狀況下所有傳空值就能夠了。上述代碼在Firefox瀏覽器運行的結果如圖11.5所示。
圖11.5  Firefox瀏覽器下運行XML DOM對象
能夠看出,在Mozilla瀏覽器中對XML的操做實際上跟IE瀏覽器中是相似的,二者均是W3C的DOM模型的一個實現。可是二者也有一些不一樣。
• 一是IE瀏覽器中結點的text屬性在Mozilla瀏覽器中變成了textContent屬性;
• 二是序列化。IE瀏覽器中的序列化簡單地使用xml屬性便可,Mozilla瀏覽器中則須要引入XMLSerializer對象。
爲了提升可移植性,能夠不使用text或textContent屬性,而利用文本子結點來建立XML片斷,代碼以下:
var text = doc.createTextNode("條目"+i);
item.append(text);
11.2.5  使用Mozilla瀏覽器支持的DOM模型解析XML片斷
下面介紹在Mozilla瀏覽器中解析XML的方式。
function traverse(doc)
{
document.write("<dl>");
var root = doc.documentElement;
document.write("<dt><u>"+root.childNodes.item(0).textContent+"</u></dt>");
for(var i=1;i<root.childNodes.length;i++)
{
node = root.childNodes.item(i);
document.write("<dd><i>"+node.textContent+"</i></dd>");
}
document.write("</dl>");
}
var parser = new DOMParser();
var doc = parser.parseFromString(xml, "text/xml");
traverse(doc);
這段解析XML的代碼與IE瀏覽器中的也很是相似,其運行結果如圖11.6所示。
圖11.6  Firefox瀏覽器運行XML DOM對象
11.2.6  基於Javascript的XML解析程序
在IE瀏覽器和Mozilla瀏覽器中操做XML的2種辦法都是基於DOM模型的,功能都至關強大,然而2個平臺上的可移植性倒是個問題。能夠經過JavaScript開發一個解析程序,來解決這個可移植性的問題。在國外,已經有人寫出了相似的程序,稱作xparse。
提示:關於xparse,能夠在 [url]http://jeremie.com/Dev/XML/[/url] 找到其主頁。
下載xparse之後能夠直接使用,可是要注意,xparse只提供讀操做。下面是一段解析XML文本的示例代碼,這段代碼在IE瀏覽器和Firefox瀏覽器中均運行正常。
<script src="xparse.js"></script>
<script>
var xml = "<items><title>標題</title><item>條目0</item><item>條目1</item><item>條目2</item></items>";
var tag = Xparse(xml);
var root = tag.contents[0];
document.write("<dl>");
document.write("<dt><u>"+root.contents[0].contents[0].value+"</u></dt>");
for(var i=1;i<root.contents.length;i++)
{
document.write("<dd><i>"+root.contents[i].contents[0].value+"</i></dd>");
}
document.write("</dl>");
</script>
運行後能夠發現運行結果與前面2種方法解析的徹底相同。
xparse並不遵循DOM規範,所以使用起來比較困難,可讀性也較差。contents屬性至關於DOM中的childNodes屬性,每一個結點經常使用的屬性包括value和type,分別表示結點的值和類型。
注意:xparse沒有提供相似text或者textContent的屬性,所以代碼中使用2個連續的contents來取得文本子結點。
xparse解決了移植性問題,可是因爲它是使用JavaScript編寫的,與IE和Mozilla的二進制代碼相比,其效率必然較低。並且,因爲其缺少對DOM規範的支持,使用很不方便。但對於Ajax而言,在傳輸的數據量都不會太大的狀況下,xparse仍然不失爲一種好的解決方案。
 

0javascript

收藏java

phelpszy

29篇文章,7W+人氣,0粉絲

Ctrl+Enter 發佈node

發佈ajax

取消json

1條評論瀏覽器

按時間倒序 按時間正序
相關文章
相關標籤/搜索