掌握 Ajax,第 7 部分: 在请求和响应中使用 XML
| 了解什么時(shí)候適合什么時(shí)候不適合使用 XML |
級(jí)別: 中級(jí) Brett McLaughlin (brett@oreilly.com), 作家,編輯, O'Reilly and Associates 2006 年 10 月 23 日 偶爾使用 Ajax 的開(kāi)發(fā)人員也會(huì)注意到 Ajax 中的 x 并意識(shí)到它代表 XML。XML 是編程中最常用的數(shù)據(jù)格式之一,對(duì)于異步應(yīng)用程序中的服務(wù)器響應(yīng)能夠帶來(lái)切實(shí)的好處。在本文中,您將看到服務(wù)器如何在請(qǐng)求響應(yīng)中發(fā)送 XML。現(xiàn)在如果不使用 XML 就不能進(jìn)行任何有意義的編程。無(wú)論考慮轉(zhuǎn)向 XHTML 的網(wǎng)頁(yè)設(shè)計(jì)人員、使用 JavaScript 的 Web 程序員、使用部署描述文件和數(shù)據(jù)綁定的服務(wù)器端程序員,還是研究基于 XML 的數(shù)據(jù)庫(kù)的后端開(kāi)發(fā)人員,都在使用這種可擴(kuò)展標(biāo)記語(yǔ)言。因此,XML 被認(rèn)為是 Ajax 底層的核心技術(shù)之一就不足為奇了。 但是,這種觀點(diǎn)反映到 Ajax 應(yīng)用程序就表現(xiàn)在其核心對(duì)象所選的名稱(chēng) —— XMLHttpRequest,這個(gè)名稱(chēng)不是很好,因?yàn)樗](méi)有反映技術(shù)上的實(shí)際情況。換句話(huà)說(shuō),多數(shù)人之所以認(rèn)為 XML 是 Ajax 的核心組成部分,僅僅是因?yàn)樗麄兿氘?dāng)然地以為 XMLHttpRequest 對(duì)象在任何時(shí)候都使用 XML。但實(shí)情并非如此,本文第一部分給出了原因。實(shí)際上,您將看到在多數(shù) Ajax 應(yīng)用程序中 XML 很少出現(xiàn)。 XML 確實(shí)有應(yīng)用在 Ajax 中,而且 XMLHttpRequest 也支持這種用法。也確實(shí)沒(méi)有什么能阻擋您向服務(wù)器發(fā)送 XML。在本系列前面的文章中,我們使用普通文本和名/值參數(shù)發(fā)送數(shù)據(jù),但 XML 也是一種可行的格式。本文將介紹如何來(lái)這樣做。但最重要的是,我將討論為何可以使用 XML 作為請(qǐng)求格式,以及為何在多數(shù)情況下不應(yīng)該使用它。 XML:到底用沒(méi)用? 對(duì) Ajax 應(yīng)用程序及它們使用 XML 的情況很容易犯想當(dāng)然的錯(cuò)誤:這種技術(shù)的名稱(chēng)(Ajax)及其使用的核心對(duì)象(XMLHttpRequest)都暗示了 XML 的使用,談到 Ajax 應(yīng)用程序的時(shí)候也經(jīng)常聽(tīng)到 XML。但是,這種觀點(diǎn)大錯(cuò)特錯(cuò),如果希望在編寫(xiě)異步應(yīng)用程序時(shí)真正做到胸有成竹,必須知道這種想法是錯(cuò)誤的,而且最好知道為什么錯(cuò)誤。 XMLHttpRequest:糟糕的名稱(chēng)和 HTTP 一項(xiàng)技術(shù)可能遇到的最糟的境況之一是它變得太炙手可熱以至于無(wú)法再改變它的一些基本內(nèi)容。XMLHttpRequest 恰恰是這種情形,它是 Ajax 應(yīng)用程序中使用的基本對(duì)象。聽(tīng)起來(lái)它似乎是為通過(guò) HTTP 請(qǐng)求發(fā)送 XML 或者以某種 XML 格式發(fā)出 HTTP 請(qǐng)求而設(shè)計(jì)的。但不論這個(gè)對(duì)象的名稱(chēng)聽(tīng)起來(lái)像什么,實(shí)際上它要做的只不過(guò)是為客戶(hù)機(jī)代碼(在網(wǎng)頁(yè)中通常是 JavaScript)提供一種發(fā)送 HTTP 請(qǐng)求的方式。僅此而已,別無(wú)其他。 因此,如果將 XMLHttpRequest 改成某種更準(zhǔn)確的名稱(chēng)可能更好一些,比如 HttpRequest,或者簡(jiǎn)簡(jiǎn)單單的 Request。但是,現(xiàn)在成千上萬(wàn)的人在應(yīng)用程序中使用了 Ajax,而且我們知道需要幾年時(shí)間(如果不是十幾年的話(huà))大部分用戶(hù)才會(huì)改用 Internet Explorer 7.0 或 Firefox 1.5 這些新版本的瀏覽器,因此這么修改實(shí)際上是不可行的。最終我們不得不使用 XMLHttpRequest,這就要求開(kāi)發(fā)人員要知道其名不符實(shí)的這一事實(shí)。 在一定程度上講,對(duì)于不支持 XMLHttpRequest 的瀏覽器(特別是在 Windows 上)的最佳回溯方法之一就是使用 Microsoft IFRAME 對(duì)象。聽(tīng)起來(lái)可不像是 XML、HTTP 或請(qǐng)求,是不是?當(dāng)然,所有這些都可能涉及到,但是這正清楚地說(shuō)明了一點(diǎn) —— XMLHttpRequest 對(duì)象更多的是關(guān)于在不重新加載頁(yè)面的情況發(fā)出請(qǐng)求,而不會(huì)太多地涉及 XML 甚至 HTTP。 請(qǐng)求是 HTTP 而非 XML 另一種常見(jiàn)的錯(cuò)誤是認(rèn)為 XML 在幕后使用 —— 坦白地說(shuō),我也曾這么認(rèn)為!但是,持這種觀點(diǎn)表明您對(duì)這種技術(shù)還不甚了解。當(dāng)用戶(hù)打開(kāi)瀏覽器從服務(wù)器上請(qǐng)求網(wǎng)頁(yè)時(shí),會(huì)輸入 http://www.google.com 或者 http://www.headfirstlabs.com 這樣的東西。即便不輸入 http://,瀏覽器也會(huì)在地址欄的這部分加上。第一部分,即 http://,是關(guān)于如何通信的很直觀的線(xiàn)索:通過(guò)超文本傳輸協(xié)議 HTTP。在網(wǎng)頁(yè)中編寫(xiě)代碼與服務(wù)器通信時(shí),無(wú)論使用 Ajax 還是普通的表單 POST,甚至超鏈接,打交道的都是 HTTP。
既然瀏覽器和服務(wù)器之間的所有 Web 通信都通過(guò) HTTP 進(jìn)行,認(rèn)為 XML 是 XMLHttpRequest 幕后所用的某種傳輸技術(shù)的想法就毫無(wú)道理了。當(dāng)然在 HTTP 請(qǐng)求中可以發(fā)送 XML,但是 HTTP 是一個(gè)精確定義的協(xié)議,短時(shí)間內(nèi)不可能消失。除了在請(qǐng)求中明確使用 XML,或者服務(wù)器用 XML 發(fā)送響應(yīng)之外,XMLHttpRequest 對(duì)象使用的只是普普通通的 HTTP。因此,當(dāng)再有人對(duì)您說(shuō) “哦,稱(chēng)為 XMLHttpRequest 是因?yàn)樵谀缓笫褂?XML” 的時(shí)候,您最好一笑了之,并耐心地解釋什么是 HTTP,告訴他們雖然 XML 可以通過(guò) HTTP 發(fā)送,但 XML 是一種數(shù)據(jù)格式而不是傳輸協(xié)議。通過(guò)這樣的討論,加深對(duì)它的理解。
使用 XML(真正) 到目前為止,我說(shuō)的只是 Ajax 在哪些地方不使用 XML。但 Ajax 中的 x 和 XMLHttpRequest 中的 XML 仍然有其實(shí)際意義,在 Web 應(yīng)用程序中使用 XML 有多種選擇。這一節(jié)將討論基本的選擇,剩下的部分再深入探討細(xì)節(jié)問(wèn)題。 XML 選項(xiàng) 在異步應(yīng)用程序中 XML 有兩種基本的用法:
其中第一種用法,即用 XML 發(fā)送請(qǐng)求,需要將請(qǐng)求的格式設(shè)置為 XML,可以使用 API 來(lái)完成,也可以與文本連成字符串,然后將結(jié)果發(fā)送到服務(wù)器。按照這種思路,主要的任務(wù)就是通過(guò)既符合 XML 規(guī)則又能被服務(wù)器理解的方式構(gòu)造請(qǐng)求。因此這里的關(guān)鍵實(shí)際上是 XML 格式,得到需要發(fā)送的數(shù)據(jù)之后,只需要用 XML 語(yǔ)法將其包裝起來(lái)。本文后面討論 XML 在 Ajax 應(yīng)用程序中的這種用法。 第二種用法,即用 XML 接收請(qǐng)求,需要從服務(wù)器上接收響應(yīng),然后從 XML 提取數(shù)據(jù)(同樣,可以用 API 或者采用蠻力方法)。這種情況下,關(guān)鍵在于來(lái)自服務(wù)器的數(shù)據(jù),而您恰好需要從 XML 中提取這些數(shù)據(jù)以便使用。這是本系列下一期文章的主題,到那時(shí)候我們?cè)僭敿佑懻摗?/p> 一點(diǎn)忠告 再詳細(xì)討論使用 XML 的細(xì)節(jié)之前,首先給您一句忠告:XML 不是一種簡(jiǎn)潔、快速和節(jié)省空間的格式。在后面幾節(jié)以及本系列的下一期文章中將看到,在上下文中使用 XML 確實(shí)有一些很好的理由,XML 與普通文本的請(qǐng)求和響應(yīng)(特別是響應(yīng))相比也確實(shí)有一些長(zhǎng)處。但是,和普通文本相比,XML 通常總會(huì)占用更多的空間,速度也更慢,因?yàn)樾枰谙⒅性黾?XML 所需要的標(biāo)簽和語(yǔ)義。 如果需要編寫(xiě)速度很快、看起來(lái)像桌面應(yīng)用的程序,XML 可能不是最佳選擇。如果從普通文本開(kāi)始,然后發(fā)現(xiàn)確實(shí)需要 XML,那么就使用它;但是如果從一開(kāi)始就使用 XML,基本上可以肯定一定會(huì)降低應(yīng)用程序的響應(yīng)性。多數(shù)情況下,與將文本轉(zhuǎn)化成下面這種 XML 相比,發(fā)送普通文本會(huì)更快一些(使用類(lèi)似 name=jennifer 的名/值對(duì)):
看看哪些地方使 XML 增加了處理時(shí)間:將文本包裝成 XML;發(fā)送額外信息(要注意我沒(méi)有包含任何包圍元素、XML 頭或者可能出現(xiàn)在實(shí)際請(qǐng)求中的其他任何內(nèi)容);讓服務(wù)器解析 XML、生成響應(yīng)、用 XML 包裝響應(yīng),并將它發(fā)送回網(wǎng)頁(yè);讓網(wǎng)頁(yè)解析響應(yīng),最后使用它。因此要清楚什么時(shí)候使用 XML,不要一開(kāi)始就認(rèn)為它在很多情況下都能夠加快應(yīng)用程序;但,它可以增強(qiáng)靈活性,這就是我們現(xiàn)在要討論的。
從客戶(hù)機(jī)到服務(wù)器的 XML 我們來(lái)看看將 XML 作為從客戶(hù)機(jī)向服務(wù)器發(fā)送數(shù)據(jù)的格式。我們首先討論技術(shù)上的實(shí)現(xiàn),然后花些時(shí)間分析什么時(shí)候適合什么時(shí)候不適合使用它。 發(fā)送名/值對(duì) 在您編寫(xiě)的 90% Web 應(yīng)用程序中,最終都會(huì)使用名/值對(duì)發(fā)送到服務(wù)器。比方說(shuō),如果用戶(hù)在網(wǎng)頁(yè)表單中輸入姓名和地址,可能希望數(shù)據(jù)采用下列形式:
如果使用普通文本把這些數(shù)據(jù)發(fā)送到服務(wù)器,可以使用清單 1 所示的代碼。類(lèi)似于本系列第一期文章中使用的那個(gè)例子。請(qǐng)參閱參考資料。 清單 1. 使用普通文本發(fā)送名/值對(duì)
將名/值對(duì)轉(zhuǎn)化成 XML 如果希望這樣使用 XML 作為數(shù)據(jù)格式,首先要做的是找到一種基本 XML 格式來(lái)存儲(chǔ)數(shù)據(jù)。顯然,名/值對(duì)可以全部轉(zhuǎn)化成 XML 元素,以其中的名稱(chēng)作為元素名,值作為元素的內(nèi)容:
當(dāng)然,XML 要求有一個(gè)根元素;如果使用文檔片段(XML 文檔的一部分)的話(huà)則需要一個(gè)封閉元素。因此可能需要將上述 XML 轉(zhuǎn)化成下面的形式:
現(xiàn)在基本上可以準(zhǔn)備在 Web 客戶(hù)機(jī)上創(chuàng)建這種結(jié)構(gòu)并發(fā)送到服務(wù)器了。 通信,口頭上的 在網(wǎng)絡(luò)上傳輸 XML 之前,需要保證服務(wù)器以及發(fā)送數(shù)據(jù)的腳本能夠接受 XML。現(xiàn)在對(duì)很多人來(lái)說(shuō)這么強(qiáng)調(diào)似乎有點(diǎn)多余,認(rèn)為這是理所當(dāng)然的,但是很多新手往往認(rèn)為只要通過(guò)網(wǎng)絡(luò)發(fā)送 XML,就能夠被正確地接收和解釋。 實(shí)際上,需要兩個(gè)步驟來(lái)保證發(fā)送的 XML 的數(shù)據(jù)能夠被正確地接收: 這兩方面都可能要求您進(jìn)行人際溝通,必須明確地告知對(duì)方!嚴(yán)格地說(shuō),如果確實(shí)需要發(fā)送 XML 數(shù)據(jù),多數(shù)腳本作者都會(huì)幫助您,因此尋找能夠接受 XML 的腳本應(yīng)該不難。但是,仍然需要保證格式是腳本所希望的格式。比方說(shuō),假設(shè)服務(wù)器接受下列格式的數(shù)據(jù):
看起來(lái)和上面的 XML 類(lèi)似,只有兩點(diǎn)不同: 從大的層面上來(lái)說(shuō),這些小問(wèn)題僅僅是服務(wù)器接收和處理數(shù)據(jù)的區(qū)別,但是服務(wù)器會(huì)徹底失敗,在網(wǎng)頁(yè)上(可能向其用戶(hù))顯示意義含糊的錯(cuò)誤消息。因此必須明確服務(wù)器的期望的格式,并把要發(fā)送的數(shù)據(jù)塞進(jìn)那種格式。然后,只有在這時(shí)才會(huì)涉及到從客戶(hù)機(jī)向服務(wù)器發(fā)送 XML 數(shù)據(jù)的真正的技術(shù)問(wèn)題。 向服務(wù)器發(fā)送 XML 當(dāng)向服務(wù)器發(fā)送 XML 的時(shí)候,更多的代碼用于獲取數(shù)據(jù)和包裝成 XML,而不是真正的傳輸數(shù)據(jù)。實(shí)際上,只要準(zhǔn)備好發(fā)送到服務(wù)器的 XML 字符串,發(fā)送工作就和普通文本一樣了,如清單 2 所示。 清單 2. 用 XML 發(fā)送名/值對(duì)
大部分代碼都很簡(jiǎn)單,只有少數(shù)地方值得提一下。首先,請(qǐng)求中的數(shù)據(jù)必須手工格式化為 XML。閱讀了三篇關(guān)于使用文檔對(duì)象類(lèi)型的文章之后,再來(lái)討論它是不是很簡(jiǎn)單了?雖然不禁止在 JavaScript 中使用 DOM 創(chuàng)建 XML 文檔,但是在通過(guò) GET 或 POST 請(qǐng)求發(fā)送到網(wǎng)絡(luò)上之前必須將 DOM 對(duì)象轉(zhuǎn)化成文本。因此使用常規(guī)字符串操作來(lái)格式化數(shù)據(jù)更簡(jiǎn)單一些。當(dāng)然,這樣很容易出現(xiàn)錯(cuò)誤和誤輸入,因此在編寫(xiě)處理 XML 的代碼時(shí)必須非常小心。 建立 XML 之后,按照和發(fā)送文本基本相同的方式打開(kāi)連接。對(duì)于 XML 最好使用 POST 請(qǐng)求,因?yàn)橛行g覽器限制了 GET 請(qǐng)求字符串的長(zhǎng)度,而 XML 可能很長(zhǎng),可以看到清單 2 中把 GET 改成了 POST 方法。此外,XML 通過(guò) send() 方法發(fā)送,而不是附加在請(qǐng)求 URL 最后的參數(shù)。這些都是非常細(xì)微的區(qū)別,很容易修改。 但是必須編寫(xiě)一行新的代碼:
看起來(lái)很難理解,它只不過(guò)是告訴服務(wù)器要發(fā)送的是 XML 而不是一般的名/值對(duì)。無(wú)論哪種情況,發(fā)送的數(shù)據(jù)都是文本,但這里使用 text/xml 或者 XML 作為普通文本發(fā)送。如果使用名/值對(duì),對(duì)應(yīng)的行應(yīng)該是:
如果忘記告訴服務(wù)器發(fā)送的是 XML,就會(huì)出現(xiàn)問(wèn)題,因此不要忘掉這一步驟。 完成這些之后,剩下的就是調(diào)用 send() 并傳入 XML 字符串了。服務(wù)器將收到您的 XML 請(qǐng)求,并(假設(shè)已經(jīng)做好了準(zhǔn)備工作)接受 XML,解釋它,然后返回響應(yīng)。實(shí)際上要做的只有這么多 —— XML 請(qǐng)求只需要稍微修改代碼。
發(fā)送 XML:好還是不好? 在結(jié)束 XML 響應(yīng)的 XML 請(qǐng)求(以及本文)之前,我們花點(diǎn)時(shí)間討論一下在請(qǐng)求中使用 XML 的感受。前面已經(jīng)提到,就傳輸而言 XML 完全不是最快的方式,但是還有更多因素要考慮。 構(gòu)造 XML 不是簡(jiǎn)單的事情 首先必須認(rèn)識(shí)到,對(duì)于請(qǐng)求來(lái)說(shuō)構(gòu)造 XML 不是簡(jiǎn)單的事。如清單 2 所示,數(shù)據(jù)很快就會(huì)和 XML 語(yǔ)義糾纏在一起:
似乎還不壞,但是要知道這是只有六個(gè)字段的 XML 片段。開(kāi)發(fā)的多數(shù) Web 表單都有十到十五個(gè)字段,雖然不一定所有的請(qǐng)求都使用 Ajax,但是應(yīng)該考慮這種情況。至少要花和實(shí)際數(shù)據(jù)同樣多的時(shí)間來(lái)處理尖括號(hào)和標(biāo)簽名稱(chēng),有可能使本來(lái)很少的輸入變得非常大。 這里的另一個(gè)問(wèn)題前面已經(jīng)提到,即必須手工創(chuàng)建 XML。使用 DOM 不是一種好的選擇,因?yàn)闆](méi)有簡(jiǎn)單易行的辦法將 DOM 對(duì)象轉(zhuǎn)化成在請(qǐng)求中發(fā)送的字符串。因此像這樣使用字符串處理是最好的辦法,不過(guò)也是一種維護(hù)起來(lái)最困難和新開(kāi)發(fā)人員最難理解的方法。在這個(gè)例子中,所有 XML 都在一行中構(gòu)造完成,如果分為多步只會(huì)更加混亂。 XML 沒(méi)有為請(qǐng)求增加任何東西 除了復(fù)雜性的問(wèn)題之外,和普通文本以及名/值對(duì)相比,在請(qǐng)求中使用 XML 實(shí)際上沒(méi)有多少好處(如果有的話(huà))。要注意,本文堅(jiān)持使用前面用名/值對(duì)發(fā)送的同一些數(shù)據(jù)(請(qǐng)參閱清單 1)來(lái)用 XML 發(fā)送。我沒(méi)有提什么數(shù)據(jù)能用 XML 但是不能用普通文本發(fā)送,這是因?yàn)閷?shí)際上沒(méi)有任何東西可用 XML 而不能用普通文本發(fā)送。 事實(shí)上這就是 XML 和請(qǐng)求的底線(xiàn):不是一定非要這么做不可。在本系列的下一期文章中將看到服務(wù)器可以使用 XML 實(shí)現(xiàn)普通文本很難做到的一些事情,但請(qǐng)求不屬于這種情況。因此除非和只接受 XML 的腳本(確實(shí)存在這樣的腳本)打交道,在請(qǐng)求中最好使用普通文本。
結(jié)束語(yǔ) 通過(guò)本文,您現(xiàn)在可能已經(jīng)開(kāi)始對(duì) Ajax 中的 XML 有一些更深的理解了。您知道 Ajax 應(yīng)用程序不一定要使用 XML,XML 也不是數(shù)據(jù)傳輸中的什么法寶。還知道從網(wǎng)頁(yè)向服務(wù)器發(fā)送 XML 不是多么難的事情。更重要的是,您知道為了確保服務(wù)器能夠處理和響應(yīng)請(qǐng)求需要做什么:必須保證服務(wù)器腳本接受 XML,而且能夠識(shí)別用于發(fā)送數(shù)據(jù)的格式。 您還應(yīng)該非常清楚 XML 對(duì)于請(qǐng)求來(lái)說(shuō)并不一定是很好的數(shù)據(jù)格式。在以后的文章中,您將看到 XML 在某些情況下是有利的,但在多數(shù)請(qǐng)求中,它只會(huì)降低速度和增加復(fù)雜性。因此雖然通常我都會(huì)建議您馬上應(yīng)用在文章中學(xué)到的內(nèi)容,但是對(duì)本文來(lái)說(shuō),我建議您在應(yīng)用這里學(xué)到的知識(shí)時(shí)最好三思而后行。XML 請(qǐng)求在 Ajax 應(yīng)用程序中有自己的價(jià)值,但是并不像您所想象的那么大。 在下一期文章中,我們將討論服務(wù)器如何使用 XML 做出響應(yīng),以及 Web 應(yīng)用程序如何處理這些響應(yīng)。令人高興的是,服務(wù)器能夠?qū)?XML 發(fā)送回 Web 應(yīng)用程序,這樣做的理由比較充分,因此那篇文章中的技術(shù)細(xì)節(jié)更實(shí)用,目前您只需要知道 XML 為何并非一定是最佳選擇 —— 至少對(duì)發(fā)送請(qǐng)求而言。您可以嘗試使用 XML 作為請(qǐng)求數(shù)據(jù)格式實(shí)現(xiàn)某些 Web 應(yīng)用程序,然后再換回普通文本,看看哪種辦法更快更簡(jiǎn)單。下一期文章再見(jiàn)。 參考資料 學(xué)習(xí)
|
轉(zhuǎn)載于:https://www.cnblogs.com/China-Dragon/archive/2010/05/07/1730142.html
總結(jié)
以上是生活随笔為你收集整理的掌握 Ajax,第 7 部分: 在请求和响应中使用 XML的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 注册MSComm方法
- 下一篇: .NET程序脱离.NET Framewo