XML和資料庫--資料傳輸
目錄
1.0 簡介
本論文簡要的探討了XML和資料庫之間的關係,同時列出一些可以使用資料庫處理XML文件的軟體。雖然這裡不打算詳盡地介紹這些軟體,但是筆者希望它能夠描述使用資料庫處理XML文件中的主要部分。這裡有點偏向與關係資料庫,因為我的經驗如此。
在開始討論XML和資料庫之前,我們需要回答一個縈繞在很多心頭的問題: "XML是資料庫嗎?"在嚴格意義上將,如果"XML"是指XML文件時,答案是"否"。儘管XML文件包含了資料,但是如果沒有其他的軟體來處理這些資料,它對於資料庫的意義和其他文字檔案沒有什麼區別。
如果在更為寬泛一些的意義上將,當"XML是指XML文件以及所有相關的XML的工具和技術時,答案則是"是"。 之所以肯定是由於XML提供了許多資料庫中所需要的部分:儲存(XML文件),結構(DTD, XML schema語言),查詢語言(XQL, XML-QL, QUILT等), 程式設計介面(SAX, DOM),等等。不過...XML還缺少很多在真實的資料庫中所必備的內容: 有效的儲存、索引、安全、交易、資料完備性、多使用者訪問、觸發、多文件查詢等。
因此如果在資料量一般、使用者較少、效能要求不高的環境下可以把XML當作資料庫來使用;而在大多產品的環境中,要求有許多的使用者使用、需要嚴格的資料完整性並且對效能有很高的要求,XML就不能勝任了。而且,考慮到象dBase和Access等資料庫既便宜又十分易用,因此甚至在第一種情況下XML都很少有理由充當資料庫的角色。
當在考慮使用XML和資料庫時,第一個要問自己的問題應該是:為什麼我需要使用資料庫?你需要將原有的資料匯出?你需要儲存你的Web主頁?你是要在一個電子商務應用中使用資料庫,而且其中XML當做傳輸的資料格式?這些問題的答案都將直接影響到你對資料庫和中介軟體(如果有的話)的選擇。
例如,假設你在電子商務應用程式中使用XML來進行資料傳輸。這是很好的方案,因為你的資料具有高度規範的結構,而XML中的那些實體和編碼對你而言並不重要了。畢竟樣你關心的僅僅是資料而不在於這些資料如何在文件中進行物理的儲存。如果你的應用程式相對比較簡單的話,關係資料庫和資料傳輸中介軟體將可以滿足你的需求;如果應用程式龐大而且複雜,那麼你就需要一個完全支援XML的開發環境了。
從另一方面來說,假設你有一個從零散的XML檔案建立的網站。你不僅需要管理這個網站,你還要提供方法讓使用者可以查詢其中的內容。這時你的檔案將非常的不規範,而實體的使用對你來說將變得很重要,因為這些檔案的結構是網站的根本。在這個例子中,你就需要某類"原生 XML"資料庫可以執行版本化、跟蹤實體的使用並且支援如XQL這樣的查詢語言。
筆者認為,在選擇資料庫時,最重要的判斷因素可能是你是利用資料庫來儲存資料還是儲存文件。如果你想儲存資料,你需要的資料庫主要是面向資料儲存(例如關係型資料庫或者面向物件型資料庫)以及在資料庫和XML文件之間相互轉換。從另一個角度來將,如果你想儲存文件,你需要一個專門設計用來儲存檔案的內容管理系統。
雖然你可以自己把檔案儲存在關係資料庫或面向物件資料庫中,可是你常會發現你的工作是在重複內容管理系統的功能。類似的,雖然一個內容管理系統通常是建立在面向物件資料庫或關係資料庫之上,但要是把一個內容管理系統當做資料庫來使用就可能非常的令人困繞。
你需要儲存資料還是文件,答案常常取決於你的XML文件。原因是XML檔案分為兩大類:以資料為中心和以文件為中心。.
以資料為中心的檔案的特點是結構相當規範、資料顆粒度好(也就是說,資料中最小的獨立單元是PCDATA元素或者是屬性)、很少或者沒有混合內容。其中同層次元素和PCDATA的出現順序並不重要。典型的例子是,XML文件包含了銷售定單、飛行安排、餐館選單等等。資料為中心的文件常被用於機器的使用,這時XML可能是多餘的---它僅僅是資料傳輸的手段而已。
例如,下面的銷售定單的文件就是以資料為中心的:
ABC Industries123 Main St.ChicagoIL60609981215
Turkey wrench:
Stainless steel, one-piece construction,
lifetime guarantee.
Stuffing separator:
Aluminum, one-year guarantee.
在XML的世界中,許多內容豐富的文件實際上都是資料為中心的。我們以顯示圖書資訊的Amazon.com網站為例。雖然這個頁面是相當巨大的文字,但是這個文字的結構是高度規範的,其中許多的部分對任何的書本描述頁面都是相同的,並且特點頁面中的各部分的大小都是有限的。也就是說,該頁面可以通過一個簡單的、資料為中心的XML文件來建立,其中包含了從資料庫中檢索得到的文字資訊以及一個XSL樣式表。通常,目前任何通過在模板中填充資料庫資料而動態構造HTML頁面的網站都可以被上面介紹的用以資料為中心的XML文件和一個或者多個的XSL樣式表方式替代。
例如,我們來看下面的租房(Lease)文件:
ABC Industries agrees to lease the property at123 Main St., Chicago, IL from XYZ Properties for a term of not less than 18 at a cost of 1000.
可以從下面的XML文件和簡單的樣式表得到:
ABC Industries123 Main St., Chicago, IL XYZ Properties181000
以文件為中心的文件的特點是:結構不規範、資料顆粒度更大(即,最小的獨立資料單元是包含有混合內容的元素或者就是整個XML文件)以及含有大量的混合內容。其中相同層次的元素和PCDATA出現順序是非常重要的。典型的例子是書、電子郵件、廣告以及大多數XHTML文件。以文件為中心的文件是用於人的使用。
例如,下面的產品描述文件就是以文件為中心:
Turkey WrenchFull Fabrication Labs, Inc.Like a monkey wrench, but not as big.The turkey wrench, which comes in both right- and left-handed versions (skyhook optional), is made of the finest stainless steel. The Readi-grip rubberized handle quickly adapts to your hands, even in the greasiest situations. Adjustment is possible through a variety of custom dials.You can:Order your own turkey wrenchRead more about wrenchesDownload the catalogThe turkey wrench costs just $19.99 and, if you order now, comes with a hand-crafted shrimp hammer as a bonus gift.
在現實情況中,以資料為中心的檔案和文件為中心的檔案之間的區別並不是很嚴格。例如,一個以資料為中心的檔案(如一張發票),也有可能包含粗顆粒度、不規則的資料(如發票的描述部分)。而一個以文件為中心檔案(如使用者手冊)也可能包含有良好顆粒度、規則的結構化資料(通常是元資料),例如作者和修訂日期。除此之外,讓你的文件具有以資料為中心或者以文件為中心的特點有助於你判斷是關心資料還是文件,這也將決定你需要採用什麼樣的系統。
要儲存或檢索資料,你可以使用一個數據庫(通常是關係型、面向物件型或者是層次型)和中介軟體(字帶或者是採用第三方),你也可以使用XML伺服器(即建立分散式應用的平臺,例如利用XML進行資料傳輸的電子商務應用)。要儲存文件,你將需要一個內容管理系統或者是一致性的DOM實現系統。有關各類系統的探討在5.0 "儲存和檢索資料" 小節和6.0 "儲存和檢索文件 " 小節。你也能夠在 XML資料庫產品 中瞭解詳細的相關產品列表。
在以資料為中心的文件中的資料內容可能來自資料庫(此時你想把資料匯出為XML格式),也可能是XML文件(此時你想把資料儲存在資料庫中)。前者的例子是在關係型資料庫中儲存的大量現有資料(或稱遺產資料);後者的例子是將資料作為XML釋出在Web中,而且你想要在你的資料庫中進行儲存以進行更多的處理。如此,根據你的需求,你可能需要將XML文件轉移到資料庫的軟體,也可能需要從資料庫轉移到XML文件的軟體,或者兩者都支援。
將資料儲存在資料庫中時,經常需要丟棄大量與文件有關的資訊,例如文件名稱和DTD,同時還有其物理結構,例如實體的定義和使用、屬性值和同層元素的順序、二進位制資料的儲存方式(是Base64編碼、是未析實體或他方式)、字元資料段和其他的編碼資訊。類似的,當從資料庫中檢索資料時,生成的XML文件結果除了非預定義實體lt(<"),gt(">"), amp("&"), apos("'"), quot(""")不包含任何CDATA或實體引用。而同層元素和屬性的出現順序也常常就是從資料庫中返回的資料的次序。
儘管一開始有些讓你吃驚,但是這常常是合理的。例如,假設你需要用XML作為資料格式把一張銷售從一個數據庫中轉移到另一個數據庫中。在這種情況下,在XML文件中並不關心銷售單的編號是儲存在銷售單的日期的前面還是後面,也不用關心是否將顧客的名稱儲存在字元資料(CDATA)段還是作為一個外部實體,或者直接當成一個PCDATA。最重要的在於相關的資料是從第一個資料庫轉移到第二個資料庫中。這樣,這個資料傳輸軟體就需要考慮資料的層次結構(該結構將銷售單的有關進行進行了分組),而其他則不必過多考慮。
忽略文件資訊以及其物理結構的後果之一是 文件的"逆反迴歸"的不一致效應,即將一個文件的資料儲存在資料庫中,然後根據這些資料重新組織成新的文件。而即便是根據標準格式處理,得到的也常常是和前面不同的文件。這是否可以接受要取決於你的需求,而且也將影響到你對資料庫和資料傳輸中介軟體的選擇。
為了在XML和資料庫之間傳輸資料,需要在文件結構和資料庫結構之間進行相互的對映。這樣的對映通常分為兩大類: 模板驅動和模式驅動。
在以模板驅動的對映中,沒有預先定義文件結構和資料庫結構之間的對映關係 ,而是使用將命令語句內嵌入模板的方法,讓資料傳輸中介軟體來處理該模板。例如,考慮下面的模板(注意該模板並不適用任何實際的產品),在<SelectStmt>元素中內嵌了SELECT語句:
<?xml version="1.0"?> <FlightInfo> <Intro>The following flights have available seats:</Intro> <SelectStmt>SELECT Airline, FltNumber, Depart, Arrive FROM Flights</SelectStmt> <Conclude>We hope one of these meets your needs</Conclude> </FlightInfo>
當資料傳輸中介軟體處理到該文件時,每個SELECT語句都將被各自的執行結果所替換,得到下面的XML格式:
<?xml version="1.0"?> <FlightInfo> <Intro>The following flights have available seats:</Intro> <Flights> <Row> <Airline>ACME</Airline> <FltNumber>123</FltNumber> <Depart>Dec 12, 1998 13:43</Depart> <Arrive>Dec 13, 1998 01:21</Arrive> </Row> ... </Flights> <Conclude>We hope one of these meets your needs</Conclude> </FlightInfo>這種以模板驅動的對映可以相當的靈活。例如,有些產品可以允許你在任何結果集合中替換你想要的內容(包括在SELECT中使用引數),而不是象上面的例子中簡單地格式化結果。另外它還支援使用程式設計來進行構造,例如迴圈和條件判斷結構。還有一些還支援SELECT語句的引數化,例如通過HTTP來傳遞引數。
目前,以模板驅動的對映只支援從一個關係型資料庫轉換成XML文件的情況。
在以模型驅動的對映中,利用XML文件結構對應的資料模型顯式或隱式地將對映成資料庫的結構,而且反之亦然。它的缺點是靈活性不夠,但是卻簡單易用,這是因為它是基於具體的資料模型來進行對映的,通常能夠為使用者實現很多地轉換工作。由於將資料從資料庫轉換成XML的結果依照了單個模型, 因此通常在這種方式下通常結合XSL來提供模板驅動的系統中所具有的靈活性。
在XML文件中的資料檢視通常有兩種模型:表格模型和特定資料物件模型。有時候也可能會出現其他的模型。例如,通過採用ID和IDREF屬性,一個XML文件可以用來一個指定的圖形。不過,很多現有的中介軟體並不支援這些模型。
許多中介軟體軟體包都採用表格模型在XML和關係型資料庫之間進行轉換。它把XML的模型看成是一個單獨的表格或者是一系列的表格。也就是說,XML的文件的結構和下面的例子相類似,其中在單個表格的情況下,<database>並不出現:
<database> <table> <row> <column1>...</column1> <column2>...</column2> ... </row> ... </table> ... </database>
其中的術語"table"可理解為單個的結果集(當從資料庫向XML中轉換資料時),或者是一個單獨的表格或可更新的檢視(當從XML向資料庫轉換資料時)。如果資料需要來自多個結果集(當資料來自資料庫中時)或者與僅僅表達成一系列表格的集合(當轉換資料到資料庫時)相比,XML的文件包含有更深層次的巢狀元素,那麼類似的轉換幾乎是不可能的。
XML文件中第二種普遍的資料模型是特定資料物件的樹型結構。在該模型中,元素型別通常對應物件,而XML中的內容模型、屬性和PCDATA則對應物件的屬性。這種模型直接對映成面向物件的資料庫和層次型資料庫,當然藉助於傳統的物件-關係對映技術和SQL 3物件檢視也可以對映成關係資料庫。要注意的是,這種模型並不是文件物件模型(DOM)。DOM是對文件本身進行建模,而不是對文件中的資料。如6.1.2小節所述,DOM用來在關係型資料庫的基礎上建立內容管理系統。
例如,上面的銷售定單文件就可以看作是由五個類所組成的樹型結構。如下面的檢視所示,包括Orders, SalesOrder, Customer, Line和Part類:
Orders | SalesOrder / | Customer Line Line | | Part Part
當把一個XML文件建模為一棵特定資料物件樹時,就沒有必要要求元素一定要對應於物件。例如,如果一個元素只包含PCDATA,如銷售定單文件中的CustName元素,它可以當作一個屬性進行處理,因此屬性只包含單一的、標量型數值。類似的,有時將混合元素或元素內容模型化成屬性也是非常有用的。一個現成的例子就是在銷售定單文件中對Description元素的處理:儘管它在XHTML的格式中有混合內容,但是將Description元素看作單個的屬性會更有用些,因為它的組成部分本身並沒有什麼意義。
本節將探討一些有關來自資料庫的XML文件的儲存問題。通常,你決定不了你選擇的中介軟體是如何解決這些問題的,但是你最好應該意識到這些問題的存在,因為這有助於你正確選擇你的中介軟體。
XML不支援任何有實際意義的資料型別。除了未析實體,所有XML文件中的資料都被當成文字來對待,即便它能夠用其他的資料型別(如日期或者整數)來表示。通常,資料轉換中介軟體將把XML文件中的文字轉換成其它資料庫中的資料型別,反之亦然。然而,特定的資料型別所識別的文字格式是有限制的,例如受到提供的JDBC Driver所支援的資料型別的限制。在這些眾多的資料型別中,日期型別通常會導致麻煩。不同國際地區的數字格式的差異也可能產生問題。
通常有兩種方法將二進位制資料儲存到XML文件中的:未析實體和Base64編碼處理(一種MIME編碼方法,可以將二進位制資料對映成US-ASCII的子集)。 對於關係型資料庫,這兩種方法都可能存在問題,因為從資料庫中儲存和檢索二進位制資料的規則非常的嚴格,這樣對會導致中介軟體出現問題。
另外,並沒有一種標準的符號用來說明一個XML文件中的元素包含有Base64編碼資料,從而使得中介軟體可能根本就不能夠識別這種編碼。最後,在儲存資料到資料庫時,可能會忽略與未析實體或Base64編碼元素相關的符號。所以,如果對你而言二進位制資料非常重要的話,請務必要確認你的中介軟體是否支援二進位制資料。
在資料庫世界中,空值(null)資料意味著資料不存在值。但是這與一個值為0的數字或長度為0的字串有很大的區別。例如,假設你的資料來自一個氣象站, 如果氣象站的溫度計出了毛病讀不出溫度值,那麼你的資料庫中將儲存一個null值而不是一個0。顯然,值為0完全是另外一回事了 。
XML中空值概念的支援可以通過設定可選的元素型別或屬性來實現。如果元素型別或屬性值為null,XML只要在文件不包含該元素或者屬性就可以了。但是對資料庫而言,空的元素或包含0長度字串的屬性並不是空值null:它們的值為長度為0的字串。
當在XML文件和資料庫結構之間相互對映過程中,你必須特別注意那些可選的元素型別或屬性是否對應於資料庫中的空值項。如果不這麼做的話,很可能出現插入錯誤(當將資料轉換到資料庫中時)或者無效文件錯誤(當將資料從資料庫讀出時)。
因為同樣要用符號空值,XML中相對與資料庫而言更為靈活。具體來講,許多XML使用者很可能包含空字串的空元素或屬性是空值。這個時候你必須考慮如何選擇合適的中介軟體來解決這個問題。一些中介軟體可以讓使用者選擇在XML文件中定義用什麼來組成空值。
根據定義,除了一些控制字元,XML文件能夠包含任何的Unicode字元。但是不幸的是,許多資料庫都限制或則不支援Unicode,而且需要一些特殊的配置才能夠處理非ASCII編碼的字元資料。如果你的資料包含了非ASCII字元,那麼務必要核實你的資料庫和中介軟體是否能夠處理這些字元。
處理指令並不屬於XML文件中的“資料”部分,因此目前許多中介軟體可能不能正常的處理。問題是,尤其是在將XML文件結構嚴格對映成資料庫結構時,處理指令通常是很難處理的,因為它們可以虛擬地出現在文件的任何位置。因此,中介軟體就很難判斷將它們儲存到什麼位置以及在什麼時候檢索讀取出來。如果處理指令和文件的迴圈回覆("round-tripping")對你而言是非常重要的話,就務必檢查你的中介軟體是如解決這個問題的。
在4.2.2 小節中提到,有時候將包含元素或者混合內容的元素不作進一步的解析而直接儲存到資料庫中是非常有用的。最常見的方法是簡單的把這個標記本身直接儲存到資料庫中。不幸的是,當從資料庫中檢索資料時將產生問題:不可能判斷資料庫中的標記到底是真的標記還是代表了標記字元的實體,如由lt和gt轉義的字元。
例如,下面的description元素:
<description> <b>Confusing example:</b> <foo/> </description>
在資料庫中儲存為:
<b>Confusing example:</b> <foo/>
這時資料庫就不能判斷<b>和<foo>是標記還是文字。有幾種可能的解決方法,如以一定的方式來標誌標記或者對非標記的標記字元使用實體。但是這時你要格外注意這樣的方式是否和使用這些的資料的其它應用相容。例如,如果你想查詢資料庫中的小於號("<")和 lt實體("<")時就要特別留心。
在XML文件和資料庫之間轉換資料時,一個普遍問題是:如何從資料庫的結構(Schema)生成XML的DTD,如果從XML的DTD產生資料庫的結構。簡而言之,這是非常直接的操作,但是產生的結果通常離許多使用者的期望值還有一些距離。
(還要注意這通常是一次性操作,而大多數應用,尤其是所有的垂直性應用都結合了已知的DTD和關係型Schema的集合。顯而易見的特例是在關係資料庫中儲存隨機XML文件或者將關係型資料釋出為XML文件的工具;而在後面的情況中,DTD的作用並不明顯。)
對於元素型別中每個有單一數值的屬性和只包含有PCDATA內容的子元素型別在該ta ble中新建立一列(欄位)。如果子元素型別或則屬性是可選的,讓該欄位允許為空。 對於每個有多值的屬性或則多僅含有PCDATA內容的子元素型別,再建立一個分開的 table來儲存他們的值,通過它們的父表的主關鍵字連線到父表。 對於每個子元素,這些子元素本身還有元素或則混合內容,使用父表中的關鍵字將 父元素表連線到子元素表中。 而下面則是一個從關係資料庫的結構生成XML文件的過程(簡化過的): 對每個table,新建一個元素。 對錶中的每列,建立一個屬性或則只含PCDATA的子元素 對每個包含有在主鍵/外來鍵關鍵字關係中主鍵值的列,新建一個子元素。
例如,下面的過程(經簡化)說明了如何從一個DTD生成一個關係型結構:
- 對於每種包含元素或者混合內容的元素型別,新建一個表格和一個主鍵欄位。
- 對於每個包含混合內容的元素型別,建立一個單獨的表格,其中存放未析資料,通過父元素主鍵連結到父表格。
- 對於此元素型別的每個單值屬性和只包含未析資料內容、只出現一次的子元素,在該表格中建立一個欄位。如果元素型別或者屬性是可選的,可以讓設定該欄位為空值。
- 對於每個多值屬性和多次出現的子元素,建立一個單獨的表格來儲存數值,並且通過父元素主鍵連結到父表格。
- 對每個有元素或者混合內容的子元素,通過父元素主鍵將父元素表格和子元素表格相連線。
下面的過程(經簡化)說明了如何從一個關係型的結構生成一個DTD:
- 對於每個表格,新建一個元素;
- 對於表格中的每個欄位,新建一個屬性或者是隻包含未析資料的子元素;
- 對於每個表格欄位中提供主鍵的主鍵/外來鍵的關係都新建一個子元素。
不幸的是,這些過程還存在著一些缺陷。例如,DTD中沒有方法預先準確地規定資料型別或者欄位長度。
因為任何的預先定義(例如通過讀取一個示例文件)在讀取其它“型別”的文件或者其他文件中包含有超過字長內容的文件時就會產生錯誤。(長久之策是使用XML schema文件的資料型別。)簡單來說,當從一關係型結構生成DTD時,是沒有辦法預先判斷子元素“應該”出現的順序或者欄位(如資料庫內部的行標識)是否該進行完全轉換。 在以上兩種情況中都可能產生命名的衝突。
儘管有這樣那樣的缺陷,但是這些方法仍然能夠很好地奠定在關係型結構和DTD之間互相轉換的起點。