1、XML的局限性
目前,許多Web網(wǎng)站的內容數據都存放在數據庫或數據文件中。對于Web程序開(kāi)發(fā)人員來(lái)說(shuō),如果要想把有用的信息從數據庫中提取出來(lái),傳統的方法是在服務(wù)器端編寫(xiě)腳本程序(如VBScript、JavaScript、CGI、ASP、Perl等等),通過(guò)對數據庫執行SQL查詢(xún)得到相關(guān)記錄,然后把查詢(xún)結果組織成HTML頁(yè)面返回給客戶(hù)端,用戶(hù)使用瀏覽器觀(guān)察最終結果。
為了提高系統服務(wù)的靈活性、可擴展性,使服務(wù)對象范圍更廣,許多商業(yè)網(wǎng)站都盡可能地把商務(wù)規則、原始數據和表現形式當做相互獨立的服務(wù)分別提供。HTML那種蘊數據于顯示之中的方式顯然不合乎這種需求。因此,把原始數據存放在XML文檔中,使用樣式單文件顯示內容是XML技術(shù)適合于電子商務(wù)的優(yōu)勢所在。但從本質(zhì)上來(lái)說(shuō),XSL技術(shù)不是面向數據顯示的,它是一種格式轉換技術(shù),在顯示手段和方式上都遠不及HTML那樣豐富。對編程人員來(lái)說(shuō),一種較為理想的方案是把HTML和XML兩種技術(shù)相結合,優(yōu)勢互補,使真正的原始數據在能夠保持本來(lái)意義和結構的同時(shí),還能充分利用HTML那千變萬(wàn)化的顯示技巧。XML數據島就是這種技術(shù)融合的產(chǎn)物,它使用<XML>標簽把XML數據直接嵌入到HTML頁(yè)面中,從而實(shí)現了二者的優(yōu)勢互補。
2、IE中數據島的處理方式
為了能夠處理這種內嵌XML代碼的HTML頁(yè)面,Internet Explorer 4.0(以下簡(jiǎn)稱(chēng)IE 4.0)引入了DSO(Data Source Objects,數據源對象)技術(shù),用Java Applet實(shí)現。
例如:
<APPLET CODE=“com.ms.xml.dso.XMLDSO.class” ID=“xmldso” WIDTH=0 HEIGHT=0 MAYSCRIPT=TRUE>
<PARAM NAME=“URL” VALUE=“myXML.xml”>
</APPLET>
上述例子中,CODE屬性指明了DSO Java小程序,MAYSCRIPT屬性保證用戶(hù)端腳本能夠處理數據對象,PARAM標簽指明了XML文檔的位置。
使用Java的局限性在于只能在HTML文檔中說(shuō)明XML的URL地址,而不能直接將XML標簽嵌入其中,這就和真正的數據島方案還有一定的差距。微軟在Internet Explorer 5.0(以下簡(jiǎn)稱(chēng)IE 5.0)中對DSO技術(shù)進(jìn)行了擴展,突破了以往的限制,使HTML和XML真正地融合到了一起。HTML頁(yè)面中支持直接使用<XML>標簽。
例如:
<HTML>
<XML ID=“xmldso”>
<?xml version=“1.0”?>
some XML……
</XML>
只要保證每個(gè)數據島的ID都是唯一的,就可以在頁(yè)面中的任何必要的地方嵌入數據島,并且這些DSO彼此都是相互獨立的。
除了上面例子中的這種直接嵌入方式,還可以使用外部引用方式鏈接數據島。
例如:
<XML ID=“xmldso” SRC=“myXML.xml”>
</XML>
這樣,只有當公司的客戶(hù)對象繼續使用IE 4.0,并且為了解決這部分客戶(hù)的兼容性問(wèn)題時(shí),Java Applet才是編程人員要考慮的選擇方案。
在IE 5.0所實(shí)現的DSO技術(shù)中,如果數據是通過(guò)SQL語(yǔ)言對數據庫進(jìn)行查詢(xún)得到的結果,那么就把它們存放在A(yíng)DO(ActiveX Data Objects)記錄集中。服務(wù)器把這種ActiveX控件(通常是ADO記錄集)發(fā)送到客戶(hù)端,由客戶(hù)端腳本程序做進(jìn)一步的處理。實(shí)際上,IE 5.0就是把XML數據島作為一種特殊的ADO記錄集進(jìn)行處理的。
3、XML的數據綁定
(1)ADO記錄集的映射
XML中的每一條主元素都被映射為ADO記錄集中的一條記錄,而子元素則相應地被映射到記錄集中的字段(也稱(chēng)為域)。
例如,存在XML數據島books.xml如下:
<XML ID=“xmldso”>
<?xml version=“1.0”?>
<booklist>
<book>
<title>Straight Talk About Computers</title>
<isbn>72-80088-005</isbn>
</book>
<book>
<title> Gourmet Microwave </title>
<isbn>72-80081-082</isbn>
</book>
</booklist>
</XML>
此時(shí),映射后的ADO記錄集為:
title isbn
Straight Talk About Computers 72-80088-005
Gourmet Microwave 72-80081-082
(2)與HTML元素的綁定
在HTML文檔中嵌入數據島之后,就可以將XML數據島與HTML元素綁定在一起。每一個(gè)DSO條目(即數據島)都有唯一的ID號。首先將HTML元素中的DATASRC屬性設置為相應的ID,就可以把HTML元素和數據島聯(lián)系在一起。然后再通過(guò)設置DATAFLD屬性值,來(lái)確定所提取的XML元素。
例如,與DIV元素綁定的代碼如下:
<DIV ID=title DATASRC=#xmldso DATAFLD=“title”></DIV>
<DIV ID=price DATASRC=#xmldso DATAFLD=“isbn”></DIV>
注意:并非所有的HTML元素都能與XML數據島綁定。目前,支持這種DSO綁定機制的元素如下:
A、APPLET、BUTTON、DIV、FRAME、IFRAME、 IMG、INPUT (此處類(lèi)型是:CHECKBOX、HIDDEN、 LABEL、PASSWORD、RADIO和TEXT)、LABEL、 MARQUEE、SELECT、SPAN、TABLE和 TEXTAREA。
(3)以表格方式顯式XML數據
若把XML數據與TABLE元素綁定在一起,就可以自動(dòng)地顯示為多行的表格形式。
例如,XML數據與TABLE元素綁定的代碼如下:
<TABLE BORDER=1 DATASRC=“#xmldso”>
<THEAD>
<TR><TH>Title</TH>
<TH>ISBN</TH></TR>
</THEAD>
<TBODY>
<TR><TD><DIV DATAFLD=“title”></DIV></TD>
<TD><DIV DATAFLD=“isbn”>
</DIV></TD></TR>
</TBODY>
</TABLE>
這樣,通過(guò)將TABLE元素中的DATASRC屬性設定為#xmldso,把兩者綁定起來(lái)。表格內部分為表頭(THEAD)和表體(TBODY)兩部分。每一個(gè)<book>元素都會(huì )顯示為一行表格,具體每一欄顯示哪一項數據,則由DIV元素中的DATAFLD屬性指定。
1、XML的嵌套處理
一般情況下,我們從數據庫中查詢(xún)得到的結果集可能很大,所以從服務(wù)器返回到客戶(hù)端時(shí),數據會(huì )被分成若干個(gè)頁(yè)面分別進(jìn)行傳遞。此時(shí),利用TABLE元素中的DATAPAGESIZE屬性可以指定每個(gè)頁(yè)面包含記錄集條目的個(gè)數。
例如:
<TABLE DATASRC=“#xmldso” DATAPAGESIZE=10>
很顯然,如果XML數據格式是對稱(chēng)的,則無(wú)論是映射到ADO記錄集還是綁定到表格元素上,效果都會(huì )很好。而在實(shí)際應用中,XML數據為非對稱(chēng)的例子也很多,比如一本書(shū)的作者可能就不止一位,這在映射和綁定時(shí)都會(huì )產(chǎn)生一定的麻煩。解決問(wèn)題的辦法就是利用嵌套。每一行表格仍對應一條主元素,每一欄也對應著(zhù)一個(gè)子元素。對于重復元素,則使用嵌套的表格。我們假設在books.xml中,第一本書(shū)的作者為Dean Straight,第二本書(shū)的作者為Charlotte Cooper、Shelley Burke和Regina Murphy。此時(shí),綁定過(guò)程如下:
● 創(chuàng )建TABLE元素,并將數據島ID賦值給DATAFLD屬性;
● 對于單獨的XML元素,如<isbn>,創(chuàng )建TD元素,并設定相應的DATAFLD屬性;
● 對于重復元素,在TD元素內部嵌套一個(gè)表格;
● 用單行單列的形式顯示作者信息。
注意這里的DATAFLD屬性必須設定為“$TEXT”,
以保證嵌套元素的內容被全部顯示在指定的元素中。
完整的HTML代碼如下所示:
<TABLE BORDER=1 DATASRC=“#xmldso”>
<THEAD><TR><TH>Title</TH>
<TH>ISBN</TH>
<TH>Author</TH></TR></THEAD>
<TBODY>
<TR><TD>
<DIV DATAFLD=“title”></DIV></TD>
<TD><DIV DATAFLD=“isbn”>
</DIV></TD>
<TD>
<TABLE BORDER=0 DATASRC=“#xmldso” DATAFLD=“author”>
<TR><TD><SPAN DATAFLD=“$Text”></SPAN></TD></TR>
</TABLE>
</TD>
</TR></TBODY>
</TABLE>
事實(shí)上,使用DSO效果最好的情況是針對結構對稱(chēng)的數據,而處理非對稱(chēng)數據更有效的辦法是使用我們以后將要介紹的DOM技術(shù)。
2、DSO技術(shù)的應用
1.訪(fǎng)問(wèn)元素的屬性
用DSO訪(fǎng)問(wèn)元素的屬性很簡(jiǎn)單,可以直接把屬性按子元素來(lái)處理。
例如:
<book isbn=“9-001-122-12”>
……
</book>
這樣,在綁定到HTML表格中時(shí),就可以直接按子元素來(lái)處理:
<TD><SPAN DATAFLD=“isbn”> </SPAN></TD>
如果遇到屬性名和子元素名一樣的情況,在元素名前加上“!”進(jìn)行區分。
2.遍歷記錄集
DSO把XML數據島當做ADO記錄集進(jìn)行處理的一大好處是可以利用ADO提供的各種方法對數據源進(jìn)行訪(fǎng)問(wèn),尤其是當把數據島與類(lèi)似SPAN、DIV和INPUT等HTML元素綁定時(shí)。通常這些元素顯示的是記錄集的首條記錄,要想對記錄集進(jìn)行遍歷瀏覽,可以使用ADO的方法 : Move、MoveFirst、MoveLast、MoveNext和MovePrevious。比如創(chuàng )建一個(gè)按鈕響應函數,只要用戶(hù)點(diǎn)擊“Next”按鈕,就可以逐條瀏覽相應的記錄。
例如:
<XML ID=“xmldso” SRC=“books.xml”>
</XML>
Sub btnNext_onclick()
xmldso.RecordSet.MoveNext
End Sub
3.與Script語(yǔ)言相結合
有些用戶(hù)比較習慣編寫(xiě)Script語(yǔ)言,利用DSO技術(shù)同樣可以與各種Script很好地結合在一起。
例如(以VB Script為例),訪(fǎng)問(wèn)記錄集時(shí),代碼如下:
Dim rsBooks
Set rsBooks = xmldso.RecordSet
訪(fǎng)問(wèn)字段(子元素)的值:
Dim sTitle
sTitle = rsBooks(“title”)
可以使用innerText和innerHTML屬性把得到的值傳遞給HTML元素。例如,有一個(gè)DIV元素名為divTitle,賦值代碼如下所示:
divTitle.innerTEXT = sTitle
利用腳本程序還可以處理許多DSO事件,下表列舉了其中的一部分事件:
事件 觸發(fā)事件 響應
onDataAvailable 新數據準備就緒 當前運行狀態(tài)中記錄集中條目的個(gè)數
onDataSetComplete 數據源中的所有數據已經(jīng)到達 顯示數據,或返回一個(gè)確認消息
onDataSetChanged 記錄集中的數據修改完畢,可以訪(fǎng)問(wèn) 顯示更新后的數據
onRowEnter 當前記錄指針已經(jīng)移動(dòng) 在顯示數據前對數據進(jìn)行必要的格式化
在腳本中處理各種事件的方法就是在<SCRIPT>標簽中使用FOR屬性指定XML數據島ID,使用EVENT屬性確定事件類(lèi)型。
例如,獲取記錄集中條目的個(gè)數:
<SCRIPT Language=“VB Script” FOR=“xmldso” EVENT=“onDataAvailable”>
lblRecords.value = booklist.RecordSet.RecordCount
</SCRIPT>
除了顯示記錄數據之外,腳本程序還可以對記錄集進(jìn)行快速查詢(xún)、排序、編輯等操作。但要指出的是,雖然ADO技術(shù)中提供了類(lèi)似SortColumn和SortAscending等方法對XML數據進(jìn)行排序,但是效果不如XSL中的排序操作,所以建議大家充分利用XSL技術(shù)來(lái)實(shí)現這部分功能。
其余的功能,如利用腳本對記錄集進(jìn)行諸如增加、刪除、修改等操作,或是分頁(yè)顯示HTML表格等等,在這里就不一一舉例說(shuō)明了,用法與前面的操作大同小異。最后需要說(shuō)明的是,所有對DSO對象的操作都是在用戶(hù)端完成的,實(shí)際上是服務(wù)器數據對象的一份復制品,這樣做的好處是避免了網(wǎng)絡(luò )承受大量數據通信的負擔。但這時(shí)用戶(hù)端所做的任何操作對服務(wù)器上存儲的數據毫無(wú)影響,如果要想對服務(wù)器記錄也進(jìn)行修改,那么就要用到客戶(hù)端與服務(wù)器端的數據交換技術(shù),我們將在以后對此進(jìn)行介紹。