国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
XML與數(shù)據(jù)庫

XML與數(shù)據(jù)庫
copyright 1999-2003 by Ronald Bourret
原作最后更新: 2003年11月
原文: www.rpbourret.com
翻譯: onestab 2004.01.23(修訂) 
俄語版 (October, 2000)
法語版 (November, 2003) 法語版的另一個地址:Patrick Peccatte


目 錄
1.0 簡介 
2.0 XML是數(shù)據(jù)庫嗎? 
3.0 為什么用數(shù)據(jù)庫? 
4.0 數(shù)據(jù)與文件 
4.1 以數(shù)據(jù)為中心的文檔 
4.2 以文檔為中心的文檔 
4.3 數(shù)據(jù),文檔和數(shù)據(jù)庫 
5.0 數(shù)據(jù)的存取 
5.1 將文檔Schema映射到數(shù)據(jù)庫Schema 
5.1.1 基于表格的映射 
5.1.2 關(guān)系 - 對象映射 
5.2 查詢語言 
5.2.1 基于模板的查詢語言 
5.2.2 基于SQL的查詢語言 
5.2.3 XML Query 語言 
5.3 在原生XML 數(shù)據(jù)庫中存儲數(shù)據(jù) 
5.4 數(shù)據(jù)類型, Null 值, 字符集, 及其他 
5.4.1 數(shù)據(jù)類型 
5.4.2 二進制數(shù)據(jù) 
5.4.3 Null 數(shù)據(jù) 
5.4.4 字符集 
5.4.5 處理指令和注釋 
5.4.6 標記的存儲 
5.5 從關(guān)系[數(shù)據(jù)庫]Schema產(chǎn)生DTD以及相反 
6.0 文件的存取 
6.1 在文件系統(tǒng)中存儲文件 
6.2 在BLOB中存儲文件 
6.3 原生XML數(shù)據(jù)庫 
6.3.1 什么是原生XML數(shù)據(jù)庫? 
6.3.2 原生XML數(shù)據(jù)庫的架構(gòu) 
6.3.2.1 基于文本的原生XML數(shù)據(jù)庫 
6.3.2.2 基于模型的原生XML數(shù)據(jù)庫 
6.3.3 原生XML數(shù)據(jù)庫的特性 
6.3.3.1 文件集 
6.3.3.2 查詢語言 
6.3.3.3 更新和刪除 
6.3.3.4 事務(wù),鎖定,以及并發(fā) 
6.3.3.5 應(yīng)用程序接口(APIs) 
6.3.3.6 雙程車票 
6.3.3.7 外部數(shù)據(jù) 
6.3.3.8 索引 
6.3.3.9 外部實體存儲 
6.3.4 規(guī)范化,引用完整性和可伸縮性 
6.3.4.1 規(guī)范化 
6.3.4.2 引用完整性 
6.3.4.3 可伸縮性 
6.4 可持久化 DOM (PDOM) 
6.5 內(nèi)容管理系統(tǒng) CMS 
7.0 XML 數(shù)據(jù)庫產(chǎn)品 
8.0 相關(guān)鏈接 
9.0 評論與反饋 
1.0 簡介 (Introduction)
本文對怎樣使用XML和數(shù)據(jù)庫進行了總體回顧,描述了以數(shù)據(jù)為中心和以文檔文中心的文檔之間的差異如何影響其在數(shù)據(jù)庫中的應(yīng)用,將XML和關(guān)系型數(shù)據(jù)庫的一起使用的常見用法,以及什么是原生XML數(shù)據(jù)庫和何時使用它。 

2.0 XML是數(shù)據(jù)庫嗎?(Is XML a Database?)
在開始討論XML和數(shù)據(jù)庫之前,我們先回答許多人都遇到過的問題:“XML是數(shù)據(jù)庫嗎?”

如果僅按數(shù)據(jù)庫這個術(shù)語的本質(zhì)來看,XML文件就是數(shù)據(jù)庫,它是數(shù)據(jù)的集合。在許多方面看起來它和其他文件沒什么區(qū)別 -- 無論如何,每個文件都含有某種類型的數(shù)據(jù)。作為一種“數(shù)據(jù)庫”格式,XML有一些優(yōu)勢:例如,它是自描述的(所用的標記描述了數(shù)據(jù)的結(jié)構(gòu)和類型,盡管缺乏語義),可交換的(portable)(Unicode),能夠以樹型或圖形結(jié)構(gòu)描述數(shù)據(jù)。同樣它也有缺點,例如,它顯得有些繁瑣,由于要對它進行解析和文本轉(zhuǎn)換,所以數(shù)據(jù)訪問速度較慢。

一個更有用的問題就是在較為寬松的意義上,XML及其周邊技術(shù)是否可以算作“數(shù)據(jù)庫” -- 數(shù)據(jù)庫管理系統(tǒng)(DBMS)。答案是“在某種程度上是(sort of)”。從正面來說,XML提供了許多數(shù)據(jù)庫所具備的東西:存儲(XML文檔), 模式(DTD, XML schema,RElAX NG 等等), 查詢語言(XQuery, XPath, XQL, XML-QL, QUILT等等),編程接口(SAX, DOM,JDOM)等等。從反面來說,它缺少一些作為實用的數(shù)據(jù)庫所應(yīng)具備的特性:高效的存儲,索引,安全,事務(wù)和數(shù)據(jù)一致性,多用戶訪問,觸發(fā)器,在查詢多個文件等等。

因此,盡管在數(shù)據(jù)量小、用戶少和性能要求不太高的環(huán)境下,可以將XML文檔用作數(shù)據(jù)庫,但是卻不適用于用戶量大、數(shù)據(jù)集成度高以及性能要求高的作業(yè)環(huán)境。

XML適合于用作所謂“數(shù)據(jù)庫”的一個好例子就是 .ini文件 -- 它包含應(yīng)用程序的配置信息。與其寫一個處理以逗號分隔(comma-delimited)的文件的解析器,開發(fā)一種小型的XML語言并寫一個解釋它的 SAX程序要容易的多。此外,XML允許使用嵌套的實體,而逗號分隔的文件(comma-delimited files)很難做到這點。然而,說它就是數(shù)據(jù)庫還很勉強,因為它是線性讀寫的,而且僅用在程序開始和結(jié)束時。

比較適合于XML數(shù)據(jù)庫的一些復雜的數(shù)據(jù)集就是個人通訊錄(名字,電話號碼,地址等),或用于描述瀏覽器書簽以及用Napster偷來的MP3。然而,由于dBase和Access之類的數(shù)據(jù)庫物美價廉,即使在這種情況下似乎也沒有多少理由把XML文件作為數(shù)據(jù)庫使用。XML的唯一真正好處就是數(shù)據(jù)的可交換性(portable),由于有越來越多的工具可以用來對數(shù)據(jù)庫進行XML序列化(serializing),這一點好處似乎也要打些折扣。 

3.0 為什么要用數(shù)據(jù)庫?(Why Use a Database?)
當你開始考慮XML和數(shù)據(jù)庫的時候,可能首先會問這個問題:為什么你會先想到使用數(shù)據(jù)庫?你是否有可用的歷史數(shù)據(jù)?是否想找個地方存儲Web頁面? 是否在電子商務(wù)中使用數(shù)據(jù)庫,而XML在其中作為數(shù)據(jù)傳輸載體? 對這些問題的回答將會極大地影響你對數(shù)據(jù)庫和中間件(如果有的話)的選擇,以及如何使用所選的數(shù)據(jù)庫。

例如,你有個電子商務(wù)的應(yīng)用,將XML用作數(shù)據(jù)交換。那么你的數(shù)據(jù)最好有個非常規(guī)則的結(jié)構(gòu)并且可供非XML程序使用。還有,XML文檔所用的某些東西如實體和編碼對你來說并不重要 --總之,你感興趣的是數(shù)據(jù),而不是它在XML內(nèi)如何存儲。在這種情況下,你大概需要一個關(guān)系型數(shù)據(jù)庫以及在XML和數(shù)據(jù)庫之間轉(zhuǎn)換數(shù)據(jù)的軟件。如果你的應(yīng)用程序是面向?qū)ο蟮?,你甚至還需要一個在數(shù)據(jù)庫或XML中存取這些對象的系統(tǒng)。

另一方面,假如你要從一些結(jié)構(gòu)松散的XML文檔建立一個網(wǎng)站。你不但要管理這個網(wǎng)站,還要提供站點內(nèi)容搜索。你的文檔看起來結(jié)構(gòu)比較松散,其中的實體的使用對你來說可能更重要,因為它們是文檔結(jié)構(gòu)的重要部分。這種情況下,你也許需要一個原生XML數(shù)據(jù)庫(native XML database)或內(nèi)容管理系統(tǒng)(content management system)。這使你可以保持文檔的物理結(jié)構(gòu),支持文件級的事務(wù)處理,以及使用XML Query語言進行查詢。 

4.0 數(shù)據(jù)和文檔 (Data versus Documents)
在選擇數(shù)據(jù)庫時最重要因素大概就是你想在數(shù)據(jù)庫存儲的究竟是數(shù)據(jù)還是文檔。例如,是簡單地把XML當作數(shù)據(jù)庫和(可能不支持XML)應(yīng)用程序之間的數(shù)據(jù)轉(zhuǎn)換工具,還是用于集成,就像XHTML和DocBook中的那樣?通常這是個偏好,但是卻非常重要,因為所有以數(shù)據(jù)為中心的(data-centric)文檔有著許多相同的特性,所有以文檔為中心的(document-centric)也有許多相同的特性。這會影響到XML在數(shù)據(jù)庫中如何存儲。下面兩部分中我們就來考察這些特性。 

(歷史背景:我在xml-dev郵件列表上第一次聽說data-centric和document-centric這些術(shù)語,不知道是誰發(fā)明的,但是我在1997的消息中發(fā)現(xiàn)有使用document-centric的,從1998年以后這兩個術(shù)語都有使用。)

4.1 以數(shù)據(jù)為中心的文檔 (Data-Centric Documents)
以數(shù)據(jù)為中心的文檔就是將XML用作數(shù)據(jù)的傳輸載體,只提供給機器消費的文檔,在此XML通常并不是絕對必要的。也就是說,對于應(yīng)用程序或數(shù)據(jù)庫而言,(在某個時間段內(nèi))數(shù)據(jù)是否以XML文檔的形式存儲并不重要。以數(shù)據(jù)為中心的文檔的例子有銷售訂單、航班時刻表、科研數(shù)據(jù)及股市匯率。 

以數(shù)據(jù)為中心的文檔的特點是結(jié)構(gòu)相當規(guī)整,數(shù)據(jù)粒度精細(fine-grained data)(即最小的獨立數(shù)據(jù)單位只存在于PCDATA元素或?qū)傩赃@一級別),很少或沒有混合內(nèi)容。除非在對文檔進行驗證的時候,同級元素或PCDATA的出現(xiàn)次序一般來說并不重要。 

以數(shù)據(jù)為中心的文檔中的這類數(shù)據(jù)可以來自數(shù)據(jù)庫(此時要輸入給XML)或在數(shù)據(jù)庫之外(此時要將其存入數(shù)據(jù)庫)。前者的一個例子就是關(guān)系數(shù)據(jù)庫現(xiàn)存的大量數(shù)據(jù);而從測量系統(tǒng)采集并轉(zhuǎn)化為XML的科研數(shù)據(jù)就是后者的例子。 

例如,下面的銷售訂單就是以數(shù)據(jù)為中心的: 

   <SalesOrder SONumber="12345">
      <Customer CustNumber="543">
         <CustName>ABC Industries</CustName>
         <Street>123 Main St.</Street>
         <City>Chicago</City>
         <State>IL</State>
         <PostCode>60609</PostCode>
      </Customer>
      <OrderDate>981215</OrderDate>
      <Item ItemNumber="1">
         <Part PartNumber="123">
            <Description>
               <p><b>Turkey wrench:</b><br />
               Stainless steel, one-piece construction,
               lifetime guarantee.</p>
            </Description>
            <Price>9.95</Price>
         </Part>
         <Quantity>10</Quantity>
      </Item>
      <Item ItemNumber="2">
         <Part PartNumber="456">
            <Description>
               <p><b>Stuffing separator:<b><br />
               Aluminum, one-year guarantee.</p>
            </Description>
            <Price>13.27</Price>
         </Part>
         <Quantity>5</Quantity>
      </Item>
   </SalesOrder>除了像銷售訂單這種顯而易見的以數(shù)據(jù)為中心的文檔之外,許多以文本為主的(prose- rich)文檔也可以是以數(shù)據(jù)為中心的。例如,Amazon.com用來顯示書籍信息的一個頁面。盡管頁面上大部分內(nèi)容都是文本,這些文本的結(jié)構(gòu)是非常規(guī)則的,許多都和其它書籍的描述相同,每個頁面特有的文本并不很多。這樣,就可以從數(shù)據(jù)庫中取出書籍的相關(guān)資料,轉(zhuǎn)換為簡單的、以數(shù)據(jù)為中心的XML文檔,再用XSL樣式表生成頁面。一般來說,那些用數(shù)據(jù)庫中的數(shù)據(jù)填充模板,動態(tài)生成HTML文件的網(wǎng)站都可以轉(zhuǎn)而使用一系列以數(shù)據(jù)為中心的XML文檔和XSL樣式表。 

例如,下面是個描述航班信息的文檔: 

   <FlightInfo>
      <Airline>ABC Airways</Airline> provides <Count>three</Count>
      non-stop flights daily from <Origin>Dallas</Origin> to
      <Destination>Fort Worth</Destination>. Departure times are
      <Departure>09:15</Departure>, <Departure>11:15</Departure>,
      and <Departure>13:15</Departure>. Arrival times are minutes later.
   </FlightInfo>從下面的XML文件和一個簡單的樣式表中創(chuàng)建這個文檔:

   <Flights>
      <Airline>ABC Airways</Airline>
      <Origin>Dallas</Origin>
      <Destination>Fort Worth</Destination>
      <Flight>
         <Departure>09:15</Departure>
         <Arrival>09:16</Arrival>
      </Flight>
      <Flight>
         <Departure>11:15</Departure>
         <Arrival>11:16</Arrival>
      </Flight>
      <Flight>
         <Departure>13:15</Departure>
         <Arrival>13:16</Arrival>
      </Flight>
   </Flights>4.2 以文檔為中心的文檔 (Document-Centric Documents)
以文檔為中心的文檔通常是供人消費的。例如書籍、email、廣告以及幾乎所有人工寫成的XHTML文件。其特性為結(jié)構(gòu)不太或根本不規(guī)則、數(shù)據(jù)粒度大(larger grained data)(最小的獨立數(shù)據(jù)單位可能存在于包含混合內(nèi)容的元素甚至整個文檔本身),混合內(nèi)容多。同級元素或PCDATA出現(xiàn)的次序一般來說總是非常重要的。 

以文檔為中心的文檔通常是以XML手工寫成,或從其他格式(如RTF, PDF, SGML)轉(zhuǎn)換到XML,與以數(shù)據(jù)為中心的文檔不同,它們的來源通常不是數(shù)據(jù)庫。(將數(shù)據(jù)插入到模板而得到的文檔是以數(shù)據(jù)為中心的;更多信息請看4.1節(jié)末尾部分)。將各種格式轉(zhuǎn)換為XML的軟件信息,請參閱XML軟件相關(guān)鏈接。 

例如,下面這個產(chǎn)品說明是以文檔為中心的: 

   <Product>

   <Intro>
   The <ProductName>Turkey Wrench</ProductName> from <Developer>Full
   Fabrication Labs, Inc.</Developer> is <Summary>like a monkey wrench,
   but not as big.</Summary>
   </Intro>

   <Description>

   <Para>The turkey wrench, which comes in <i>both right- and left-
   handed versions (skyhook optional)</i>, is made of the <b>finest
   stainless steel</b>. The Readi-grip rubberized handle quickly adapts
   to your hands, even in the greasiest situations. Adjustment is
   possible through a variety of custom dials.</Para>
   
   <Para>You can:</Para>
   <List>
   <Item><Link URL="Order.html">Order your own turkey wrench</Link></Item>
   <Item><Link URL="Wrenches.htm">Read more about wrenches</Link></Item>
   <Item><Link URL="Catalog.zip">Download the catalog</Link></Item>
   </List>
   
      <Para>The turkey wrench costs <b>just $19.99</b> and, if you
   order now, comes with a <b>hand-crafted shrimp hammer</b> as a
   bonus gift.</Para>
   
   </Description>
   
   </Product>
4.3 數(shù)據(jù)、文檔和數(shù)據(jù)庫(Data, Documents, and Databases)
在現(xiàn)實當中,以數(shù)據(jù)為中心和以文檔為中心的文檔之間的差別不一定很明顯。例如,另一種以數(shù)據(jù)為中心的文檔比如發(fā)票,可能含有大粒度的、結(jié)構(gòu)不規(guī)則的數(shù)據(jù)比如零件說明;另一種以文檔文中心的文件如用戶手冊,可能包含細粒度的結(jié)構(gòu)規(guī)則的數(shù)據(jù)(通常為元數(shù)據(jù))比如作者和修訂日期。其它例子包括法律和醫(yī)學文書,雖然以松散的形式寫成但是卻包含離散的數(shù)據(jù)塊例如日期、名稱和操作程序,出于法規(guī)的原因通常要以完整的文件形式存儲。

除此之外,弄清文件的這兩種特點有助于選擇數(shù)據(jù)庫的類型。一般來說,將數(shù)據(jù)存儲于傳統(tǒng)的數(shù)據(jù)庫,例如關(guān)系型,面向?qū)ο笮突驅(qū)哟涡蛿?shù)據(jù)庫。這可由第三方的中間件完成或由數(shù)據(jù)庫本身提供內(nèi)在支持。對于后者,該數(shù)據(jù)庫被稱作支持XML的(XML-enabled)。文檔可被存儲在原生(native)XML數(shù)據(jù)庫(專為存儲XML而設(shè)計的數(shù)據(jù)庫)或內(nèi)容管理系統(tǒng)(建在原生XML數(shù)據(jù)庫之上專門用來管理文檔的程序)。

這些原則并不是絕對的。如果對XML特有的功能不很看重,數(shù)據(jù),特別是半結(jié)構(gòu)化的數(shù)據(jù)可以存儲在原生XML數(shù)據(jù)庫,文檔也可以存儲到傳統(tǒng)數(shù)據(jù)庫。何況傳統(tǒng)數(shù)據(jù)庫與原生XML數(shù)據(jù)庫之間的界限越來越模糊,傳統(tǒng)數(shù)據(jù)庫增加了原生XML的能力,而原生XML數(shù)據(jù)庫增加了對文檔存儲在外部(通常為關(guān)系型)數(shù)據(jù)庫的支持。 

本文剩下的部分就有關(guān)數(shù)據(jù)(第5節(jié))和文檔(第6節(jié))的存儲和讀取的策略與問題展開討論。關(guān)于最新的XML數(shù)據(jù)庫產(chǎn)品,請見XML數(shù)據(jù)庫產(chǎn)品。 

5.0 數(shù)據(jù)的存取(Storing and Retrieving Data)
為了在XML文件和數(shù)據(jù)庫之間交換數(shù)據(jù),必須將XML文件的schema(DTD,XML Schema, RELAX NG等)映射到數(shù)據(jù)庫的schema。用于數(shù)據(jù)轉(zhuǎn)換的軟件位于這種映射的上層。該軟件可以使用XML Query語言(如XPath,XQuery,或其他專用語言)或簡單地按照映射(SELECT * FROM Table的XML對應(yīng)形式)轉(zhuǎn)換數(shù)據(jù)。

對于后者,文檔的結(jié)構(gòu)必須完全符合映射所要求的結(jié)構(gòu)。由于通常不易做到這點,使用這種策略的產(chǎn)品一般要和XSLT一起使用。在數(shù)據(jù)轉(zhuǎn)換到數(shù)據(jù)庫之前,先將文件按照映射所要求的結(jié)構(gòu)進行轉(zhuǎn)換,然后轉(zhuǎn)存數(shù)據(jù)。相應(yīng)地,數(shù)據(jù)從數(shù)據(jù)庫中取出以后,結(jié)果文件要被轉(zhuǎn)換成應(yīng)用程序所需的結(jié)構(gòu)。

5.1 映射[XML]文件Schema到數(shù)據(jù)庫Schema (Mapping Document Schemas to Database Schemas)
文件schema到數(shù)據(jù)庫schema的映射是在元素類型、屬性和文本上進行的。這時幾乎總是忽略物理結(jié)構(gòu)(例如實體、CDATA部分及編碼信息)及某些邏輯結(jié)構(gòu)(如處理指令、注釋以及元素和PCDATA在父元素內(nèi)出現(xiàn)的順序)。這樣做是自然而然的,因為數(shù)據(jù)庫和應(yīng)用程序只需關(guān)心XML文件中的數(shù)據(jù)。例如,在上述的銷售訂單中,客戶代號是在CDATA部分,還是外部實體中,或直接就是PCDATA并不重要,同樣,客戶代號出現(xiàn)在訂貨日期之前或之后也無關(guān)緊要。

這種方法的一個后果是能否保證文件有“往返車票” -- 將文件中的數(shù)據(jù)存入數(shù)據(jù)庫后,又從數(shù)據(jù)庫中的數(shù)據(jù)重新構(gòu)建文件,得到的文件往往和原來的文件不同(哪怕從最簡單的角度來講)。這種情形是否可以接受取決于你的要求,在選擇軟件時要考慮到這一點。 

將一個XML文件的schema映射到數(shù)據(jù)庫的schema有兩種方法:基于表格的映射和對象-關(guān)系映射。 

5.1.1 基于表格的映射 (Table-Based Mapping)
許多轉(zhuǎn)換XML到數(shù)據(jù)庫的中間軟件都采用基于表格的映射。它把XML文件看作一個(或一組)表格,也就是說,XML文件的結(jié)構(gòu)必須是下面這種樣子,如果只是單一表格的話,就不再需要<database>元素和其他<table>元素: 

   <database>
      <table>
      <row>
           <column1>...</column1>
            <column2>...</column2>
            ...
         </row>
         <row>
            ...
         </row>
         ...
      </table>
      <table>
         ...
      </table>
      ...
   </database>
根據(jù)所用軟件的不同,可以將各字段數(shù)據(jù)以子元素的形式或以屬性的形式存儲,同樣也可以指定這些元素或?qū)傩缘拿?。此外,采用基于表格映射方式的軟件還可能允許在文件開始的地方包含表格或各字段的元數(shù)據(jù),或者將其作為各表格或元素的屬性。注意這里所說的“表格”是泛指的表格。當將數(shù)據(jù)從數(shù)據(jù)庫中轉(zhuǎn)到XML文件時,“表格”可以是任何結(jié)果集,反之,“表格”可以是普通的表格或可更新的視圖。 

基于表格的映射對存取關(guān)系型數(shù)據(jù)比較適用,比如在兩個關(guān)系型數(shù)據(jù)庫之間轉(zhuǎn)換數(shù)據(jù)。其明顯不足就是不適于格式不符的XML文件。 

5.1.2 對象-關(guān)系映射 (Object-Relational Mapping)
所有支持XML的關(guān)系型數(shù)據(jù)庫和某些中間件都可以使用對象-關(guān)系的映射方式。它將XML文件中的數(shù)據(jù)視為特定的對象樹的模型。在這個模型中,元素及其類型、元素內(nèi)容或混合內(nèi)容(復合元素類型)通常被視為類。只具有PCDATA內(nèi)容的元素(簡單元素類型)、屬性以及PCDATA都被當作簡單屬性。然后通過傳統(tǒng)的對象-關(guān)系映射技術(shù)或 SQL 3的對象視圖將該模型映射到關(guān)系型數(shù)據(jù)庫。也就是說,類被映射到表格,簡單屬性被映射到字段,而值為對象屬性被映射為成對的主鍵/外鍵(primary key/foreign key)。

(所謂“對象-關(guān)系映射”有些名不副實。因為對象樹可以被直接映射到面向?qū)ο笮秃蛯哟涡蛿?shù)據(jù)庫,然而,但是由于大多數(shù)使用這種映射方式的主流產(chǎn)品使用的其實是關(guān)系型數(shù)據(jù)庫,所以“對象-關(guān)系映射”也就廣為人知。) 

我們在理解這種映射所用的對象模型的時候要知道,這個對象模型不是文件對象模型(DOM)。所有XML文件的DOM都是一樣的,而上述描述文件數(shù)據(jù)的模型對于每個DTD所定義的XML文件都不一樣,例如,上述銷售訂單的模型是一個由四個類所組成的對象樹--SalesOrder, Customer, Item, 和Part, 如下圖所示: 

                    SalesOrder
                   /    |    \
             Customer   Item   Item
                         |      |
                        Part   Part
在由同一個文件產(chǎn)生的DOM中,對象樹的組成是元素、屬性和文本:

                          元素 --- 屬性
                    (SalesOrder) (SONumber)
               ____/   /   \   \_____
              /       /     \        \
          元素      文本     元素     元素
     (Customer) (OrderDate)  (Item)    (Item)
          |                    |         |
         etc.                 etc.      etc.
模型中的對象是否被實例化要取決于所用的軟件。有些軟件允許依據(jù)模型產(chǎn)生類,然后可以在程序中使用由這些類所產(chǎn)生的對象。在這些產(chǎn)品中,數(shù)據(jù)是在XML文件 - 對象 -數(shù)據(jù)庫之間傳遞的。其他產(chǎn)品是直接在XML文件和數(shù)據(jù)庫之間進行數(shù)據(jù)轉(zhuǎn)換的,對象只是作為這種過程的可視化幫助工具。生成這些中間對象是否有用完全取決于你的應(yīng)用程序。 

(根據(jù)Sun的 Java Architecture for XML Binding,XML文件與對象的綁定通常被稱為XML數(shù)據(jù)綁定(XML data binding),有些產(chǎn)品支持XML數(shù)據(jù)綁定,其中許多還可以在對象和數(shù)據(jù)庫之間進行數(shù)據(jù)交換,更多的信息,請看 XML數(shù)據(jù)綁定相關(guān)資源 XML Data Binding Resources.)

各種產(chǎn)品對對象-關(guān)系映射的具體支持各不相同。例如:

所有產(chǎn)品都支持從復合元素類型到類,以及從簡單元素類型和屬性(attributes)到[類的]屬性(properties)的映射。 
所有(?)產(chǎn)品都允許你指定是否將根元素映射到對象模型或數(shù)據(jù)庫。如果你想在同一個XML文檔中存儲多個頂級對象時,這個包裝元素(wrapper element)就顯得有用了。例如,如果你想在同一個XML文件中存儲多個銷售訂單,就必須把它們包裝在一個根元素內(nèi)。

當使用基于表格的映射的XML文件有多個表格組成時,這個包裝元素就相當于<database>元素,他的存在只是為了滿足 XML 文件只能有一個根元素的要求。少數(shù)產(chǎn)品允許你就像指定包裝元素那樣,在較低的層次上指定[某些元素是否被映射 -譯注]。 

大多數(shù)產(chǎn)品允許你說明將[對象的]屬性(properties)映射到XML文件中的屬性(attribute)還是子元素。某些產(chǎn)品還允許你混合使用屬性和子元素,其他的只允許你使用兩者之一。 
大多數(shù)產(chǎn)品允許XML文件和數(shù)據(jù)庫的名字可以不同。少數(shù)產(chǎn)品要求必須使用相同的名字。 
大多數(shù)產(chǎn)品允許你說明子元素在父元素中的出現(xiàn)次序,盡管如此,仍然不可能建立多個內(nèi)容模型。幸好對于大多數(shù)以數(shù)據(jù)為中心的文檔而言,所支持的內(nèi)容模型已經(jīng)足夠。(當文件需要驗證時,子元素的次序才顯得相當重要。) 
某些產(chǎn)品允許你將復合元素類型映射到簡單屬性 (properties)。當某個元素包含混合內(nèi)容(例如銷售訂單中的< Description>元素)時,這點相當有用。盡管<Description>元素像XHTML一樣包含子元素和文本,但最好還是將這個description視為單個屬性,而不是把它分成許多碎塊。 
支持混合內(nèi)容中的PCDATA映射的產(chǎn)品不多。 
關(guān)于對象-關(guān)系型映射的詳細描述,請看第三部分“將DTD映射到數(shù)據(jù)庫”。 

5.2 查詢語言(Query Languages)
許多產(chǎn)品都是按照它們所建的模型直接進行數(shù)據(jù)交換。由于XML文件的結(jié)構(gòu)和數(shù)據(jù)庫的結(jié)構(gòu)一般不同,這些產(chǎn)品一般都使用了或包括了XSLT樣式表。這就允許用戶在數(shù)據(jù)被交換到數(shù)據(jù)庫之前(或相反)根據(jù)模型規(guī)定的格式對文件進行轉(zhuǎn)換。由于XSLT處理的代價較高,某些產(chǎn)品只提供有限幾種這樣的轉(zhuǎn)換。 

這個問題的長久解決方案就是設(shè)計一種可以返回XML[文件]的查詢語言。目前來看(2002年11月),大多數(shù)這種語言都依賴于在模板中嵌入 SELECT 語句。到 XQuery 最后定稿時這個局面有望得到改變,正如主流的數(shù)據(jù)庫產(chǎn)品提供商已經(jīng)做的那樣。不幸的是,幾乎所有的XML查詢語言(包括 XQuery1.0 和 SQL/XML的最初發(fā)布版本)對文件都是只讀的,所以短期來說,最需要的是能夠插入、更新、刪除數(shù)據(jù)的手段。(從長遠來看,XQuery 和 SQL/XML 將會增加這種功能。) 

5.2.1 基于模板的查詢 (Template-Based Query)
大多數(shù)從數(shù)據(jù)庫讀取XML的查詢語言是基于模板的,這些語言并沒有預先定義XML文件和數(shù)據(jù)庫之間的映射,相反,是將SELECT語句嵌入到模板中,由數(shù)據(jù)交換軟件對結(jié)果進行處理。例如,下面的模板(并不是真正產(chǎn)品中的)使用包含了SELECT語句和$column-name值的< SelectStmt>元素來決定將結(jié)果放在何處。  

<?xml version="1.0"?>
   <FlightInfo>
      <Introduction>The following flights have available seats:</Introduction>
      <SelectStmt>SELECT Airline, FltNumber, Depart, Arrive FROM Flights</SelectStmt>
         <Flight>
            <Airline>$Airline</Airline>
            <FltNumber>$FltNumber</FltNumber>
            <Depart>$Depart</Depart>
            <Arrive>$Arrive</Arrive>
         </Flight>
      <Conclusion>We hope one of these meets your needs</Conclusion>
   </FlightInfo>
這個模板處理之后的結(jié)果可能是:

<?xml version="1.0"?>
   <FlightInfo>
      <Introduction>The following flights have available seats:</Introduction>
      <Flights>
         <Flight>
            <Airline>ACME</Airline>
            <FltNumber>123</FltNumber>
            <Depart>Dec 12, 1998 13:43</Depart>
            <Arrive>Dec 13, 1998 01:21</Arrive>
         </Flight>
         ...
      </Flights>
      <Conclusion>We hope one of these meets your needs.</Conclusion>
   </FlightInfo>
基于模板的查詢語言非常靈活。盡管各個產(chǎn)品的功能不盡相同,但有一些共同特性: 

可以將返回結(jié)果放在輸出文件中的任何地方,包括作為后續(xù)SELECT語句的參數(shù)。 
可由程序構(gòu)建 for 循環(huán)和 if 語句。 
可以定義變量和函數(shù)。 
可通過HTTP參數(shù)實現(xiàn)SELECT語句的參數(shù)化(parameterization)。 
從關(guān)系數(shù)據(jù)庫中將數(shù)據(jù)轉(zhuǎn)換到XML文件時,幾乎一定要用到基于模板的查詢語言。雖然有些產(chǎn)品也將基于模板的查詢語言用于XML文件到關(guān)系數(shù)據(jù)庫的數(shù)據(jù)轉(zhuǎn)換,這時所用的并不是完整的模板語言。相反,他們使用的是上面所述的基于表格的映射。 

5.2.2 基于SQL的查詢語言 (SQL-Based Query Languages)
基于SQL的查詢語言使用的是經(jīng)過修改的SELECT語句,[查詢]結(jié)果被轉(zhuǎn)換為XML。目前已經(jīng)有一些私有的基于SQL的語言可用。通過簡單地使用嵌套的SELECT語句,就可直接轉(zhuǎn)換成符合對象 - 關(guān)系映射的嵌套的XML。或者使用SQL 3的對象視圖也可直接轉(zhuǎn)換成XML。最后還可使用 OUTER UNION 語句和特殊標記來決定怎樣將結(jié)果轉(zhuǎn)換成 XML。

除了這些私有語言以外,2000年一些公司聯(lián)合提出了 SQL 的 XML 擴展標準,現(xiàn)在已經(jīng)成為被稱為 SQL/XML 的 ISO SQL 標準的一部分;最終可望于2003年得到批準。 SQL/XML 引入了一種 XML 數(shù)據(jù)類型,并且為 SQL 增加了幾個函數(shù),可以從關(guān)系型數(shù)據(jù)構(gòu)造 XML 元素和屬性。

例如,下面的查詢

SELECT Orders.SONumber,
 XMLELEMENT(NAME "Order",
  XMLATTRIBUTES(Orders.SONumber AS SONumber),
  XMLELEMENT(NAME "Date", Orders.Date),
  XMLELEMENT(NAME "Customer", Orders.Customer)) AS xmldocument
FROM Orders
構(gòu)造了具有兩個字段的結(jié)果集。第一個字段為銷售訂單號,第二個字段為一個 XML 文件。每一行有一個 XML 文件,它來自 Orders 表中相應(yīng)的數(shù)據(jù)。例如,從訂單號 123 生成的 XML 文件是:

<Order SONumber="123">
 <Date>10/29/02</Date>
 <Customer>Gallagher Industries</Customer>
</Order>
在網(wǎng)上很難找到有關(guān) SQL/XML 的資料。關(guān)于其介紹和(可能)過時的一些資料,請參考 SQLX Group 網(wǎng)站 。 SQL/XML 標準的拷貝可從 sqlstandards.org 的FTP 目錄得到(ftp://sqlstandards.org/SC32/WG3/Progression_Documents/Informal_working_drafts/)。你要找的文件名應(yīng)當是WD5-14-xml-yyyy-mm.pdf 或 wd5-14-xml-yyyy-mm.pdf, 這里 yyyy-mm 是標準的年月。比如2003年11月的最新標準的文件名為 WD5-14-xml-2003-09.pdf。注意 sqlstandards.org 的 FTP 站點經(jīng)常宕機,你可能要不斷嘗試才行。另外還可以在 Google 上搜索 XMLFOREST 或 XMLAGG。 

5.2.3 XML Query Languages
基于模板和基于SQL的查詢語言只能用于關(guān)系數(shù)據(jù)庫,與此不同,XML查詢語言可用于任何XML文檔。為了把它用于關(guān)系數(shù)據(jù)庫,必須把數(shù)據(jù)庫中的數(shù)據(jù)看作XML的模型,這樣才能對虛擬的XML文件進行查詢。 

對于XQuery,基于表格的映射或?qū)ο?關(guān)系型映射都可以使用。當使用基于表格的映射時,各個表格被視為單獨的文件,像SQL中的一樣, 這些表格的結(jié)合(joints)則在查詢[語句]本身中指明。如果使用的是對象-關(guān)系型映射,各個表格的層次被當作單個文件,而[表格的]結(jié)合在映射中說明。對于大多數(shù)關(guān)系數(shù)據(jù)庫而言,似乎基于表格的映射更為常用,這是因為它的實現(xiàn)似乎更簡單些,SQL的用戶對此也更為熟悉。 

如果使用XPath在多個表格中進行查詢,就必須使用對象-關(guān)系映射,這是因為XPath不支持多個文檔的聯(lián)合。因此,如果使用基于表格的映射,也許每次只對一個表格進行查詢最好。 

5.3 原生XML數(shù)據(jù)庫的數(shù)據(jù)存儲(Storing Data in a Native XML Database)
還可以將XML文件中的數(shù)據(jù)存儲在原生XML數(shù)據(jù)庫(native XML database)中。這么做有幾個理由。首先,當你的數(shù)據(jù)是半結(jié)構(gòu)化的數(shù)據(jù)時。也就是說,它的結(jié)構(gòu)是普通的,但是如果將其映射到關(guān)系數(shù)據(jù)庫,結(jié)果是要么出現(xiàn)大量空值(null)的字段,要么表格的數(shù)量過多,浪費空間或效率低下。雖然半結(jié)構(gòu)化的數(shù)據(jù)可存儲到面向?qū)ο蟮幕驅(qū)哟涡蛿?shù)據(jù)庫中,你還可以選擇將它以XML文件的形式存儲于原生XML數(shù)據(jù)庫。 

將數(shù)據(jù)存儲在原生XML數(shù)據(jù)庫中的第二個理由是讀出速度。根據(jù)XML數(shù)據(jù)庫存儲數(shù)據(jù)的物理方式的不同,數(shù)據(jù)的讀出速度可以做到比關(guān)系型數(shù)據(jù)庫[的讀取速度]快得多。其原因是,原生XML數(shù)據(jù)庫對整個文件一起進行物理存儲,和[表示]文件各個部分的物理(而不是邏輯)指針可采用同一存儲策略。這就可以不使用連接(joins)或只使用物理連接讀取文件,無論哪種情況都比關(guān)系型數(shù)據(jù)庫所用的邏輯聯(lián)結(jié)要快。 

以上述銷售訂單文件為例。在關(guān)系型數(shù)據(jù)庫中,它可能被存為四個表格 -- SalesOrders, Items, Customers, 和 Parts -- 讀取文件時需要將這些表格結(jié)合起來。在原生XML數(shù)據(jù)庫中,整個文件可被存儲在磁盤的一個地方,在讀取文件或其片斷時只需要一次查找和一次讀取操作。關(guān)系數(shù)據(jù)庫在讀取數(shù)據(jù)時則需要四次查找以及至少四次讀取操作。 

這樣做的一個明顯缺點就是,只有數(shù)據(jù)的讀取順序和寫入磁盤的順序相同時,才可以提高速度。如果你想要的數(shù)據(jù)視圖不同,比如只想要客戶及其訂單列表,性能可能比關(guān)系數(shù)據(jù)庫更差。所以,如果你的應(yīng)用中是單個數(shù)據(jù)視圖為主,為了提高性能,才可以考慮將數(shù)據(jù)存儲到原生XML數(shù)據(jù)庫。 

將數(shù)據(jù)存儲在原生XML數(shù)據(jù)庫中的第三個理由是你想利用XML的獨有特性,如執(zhí)行XML查詢。由于今天以數(shù)據(jù)為中心的應(yīng)用幾乎沒有這樣做的,而且關(guān)系數(shù)據(jù)庫正在逐步支持XML查詢語言,這個理由越來越不充分。 

將數(shù)據(jù)存儲在原生XML數(shù)據(jù)庫中的一個問題是,大多數(shù)原生數(shù)據(jù)庫只能以XML[的形式]返回數(shù)據(jù)。(支持元素和屬性到應(yīng)用程序變量綁定的只是少數(shù))。如果你的應(yīng)用程序需要另一種數(shù)據(jù)格式(很有可能),使用數(shù)據(jù)之前必須先解析XML。對本地的應(yīng)用程序而言顯然是個缺點,而這種前期準備在(比如)ODBC中就不存在。對于將XML作為數(shù)據(jù)載體使用的分布式應(yīng)用程序而言,這個問題不很嚴重,因為不管用的是哪種數(shù)據(jù)庫,這種前期工作必須要有。 

5.4 數(shù)據(jù)類型,空值,字符集,諸如此類 (Data Types, Null values,Character Sets, and All That Stuff)
本節(jié)將就在傳統(tǒng)數(shù)據(jù)庫中存儲XML文件數(shù)據(jù)的相關(guān)問題展開討論。(有關(guān)數(shù)據(jù)類型和二進制數(shù)據(jù)存儲的討論同樣適用于原生XML數(shù)據(jù)庫)總的說來,你無法選擇數(shù)據(jù)交換軟件解決這些問題的方式。然而,你應(yīng)當明白這些問題確實存在,這樣會有助于你選擇軟件。 

5.4.1 數(shù)據(jù)類型 Data Types
如果單從字面上講,XML并不支持任何數(shù)據(jù)類型。除了非解析實體,XML文件中的所有數(shù)據(jù)都是文本,盡管它可能表示日期或整數(shù)等其他類型。一般來說,數(shù)據(jù)交換軟件負責把(XML文件中的)文本轉(zhuǎn)換成(數(shù)據(jù)庫中的)其他數(shù)據(jù)類型,反之亦然。

至于軟件如何確定該進行怎樣的轉(zhuǎn)換各不相同,常見的有兩種方法。第一種方法是軟件根據(jù)數(shù)據(jù)庫模型來確定數(shù)據(jù)類型,因為它在運行時總是可用的。(而XML模型在運行時就不一定有,甚至根本就不存在)。第二種方法就是由用戶明確指定數(shù)據(jù)類型,比如映射信息。它可以由用戶寫出,或者自動從數(shù)據(jù)庫模型或XML 模型中產(chǎn)生。

類型轉(zhuǎn)換時的另一個問題是,究竟能夠識別(從 XML 轉(zhuǎn)換)或創(chuàng)建什么文本格式。大多數(shù)情況下,能夠被識別為特定數(shù)據(jù)類型的文本格式數(shù)目很有限,比如某個JDBC驅(qū)動程序支持單一的、特定的格式。日期看起來最容易出問題,因為它的格式可能非常多。而數(shù)字在各種語言中的格式也不盡相同,也有可能出問題。

5.4.2 二進制數(shù)據(jù) (Binary Data)
二進制數(shù)據(jù)在XML文件中的存儲方法一般有三種:非解析實體和Base64編碼(一種 MIME 編碼方式,將二進制數(shù)據(jù)映射到US-ASCII碼的一個子集[0-9a-zA-Z+/] - 見RFC 2045 );十六進制編碼(每二進制字節(jié)用兩個十六進制字符[0-9a-fA-F]表示)以及非解析實體(二進制數(shù)據(jù)存儲在與該XML分離的物理實體內(nèi))。

二進制數(shù)據(jù)的最大問題在于數(shù)據(jù)轉(zhuǎn)換產(chǎn)品對它的支持不夠,所以要檢查你的軟件是否支持。另一個問題是,大部分(全部?)數(shù)據(jù)轉(zhuǎn)換產(chǎn)品都不存儲符號和實體聲明。這樣,將 XML 中的數(shù)據(jù)轉(zhuǎn)換到數(shù)據(jù)庫中時,與某些實體對應(yīng)的符號就會丟失。(關(guān)于符號的更多信息詳見 XML 標準的 4.7 部分)。

5.4.3 空數(shù)據(jù) (Null Data)
在數(shù)據(jù)庫術(shù)語中,空數(shù)據(jù)(null data)意味著沒有數(shù)據(jù)。這和值為0的數(shù)字或長度為零的字符串區(qū)別非常大。例如,假設(shè)你收集到的是氣象數(shù)據(jù),如果溫度計不能工作,則數(shù)據(jù)庫中存儲的就是null而不是0,否則情況就完全不同了。 

XML也支持這種空數(shù)據(jù)的概念(通過可選(optional)元素或?qū)傩?。如果一個可選元素或?qū)傩缘闹禐榭?,就不會包含在文件?nèi)。而在數(shù)據(jù)庫中,值為零長度字符串的屬性和空元素并不是null:它們的值為零長度的字符串。

當你將XML文檔的結(jié)構(gòu)映射到數(shù)據(jù)庫(或反過來)時,你當特別留意,可選元素類型或[空值]屬性會被映射到允許空值的字段(nullable columns),反之亦然。如果不是這樣的話,可能會產(chǎn)生插入錯誤(當轉(zhuǎn)換數(shù)據(jù)到數(shù)據(jù)庫時)或非法文件錯誤(從數(shù)據(jù)庫中取出數(shù)據(jù)時)。

與數(shù)據(jù)庫專業(yè)相比,XML社區(qū)對null含義的表示法更為自由-- 特別是許多XML用戶都認為零長度字符串的屬性和空元素是“空(null)”的,所以你應(yīng)該檢查一下你的軟件是如何處理這種情況的。有些軟件為用戶提供了選擇,可以定義XML中如何表示"null",以及支持XML Schema中的 xsi:null屬性。 

5.4.4 字符集 (Character Sets)
根據(jù)定義,除了某些控制字符,XML文件可包含任何Unicode字符。不過,許多數(shù)據(jù)庫對Unicode的支持很有限或根本就不支持,而且需要特殊的配置才能處理非ASCII字符。如果你的文件包含非ASCII字符,要確保你的數(shù)據(jù)庫及數(shù)據(jù)轉(zhuǎn)換軟件對這些字符是否支持及如何支持的。 

5.4.5 處理指令和注釋 (Processing Instructions and Comments)
處理指令和注釋并不是XML文檔“數(shù)據(jù)”的一部分,大多數(shù)(全部?)數(shù)據(jù)轉(zhuǎn)換軟件都不能處理它們。問題在于這些東西可能出現(xiàn)在XML文檔中的任何地方,所以不容易進行基于表格或?qū)ο?關(guān)系型映射。(一個明顯行不通的方案是為這些處理指令和注釋建立一個表格,在其他表格加上指向這個表格的外部鍵(foreign key),每當處理別的表格時,就檢查這些表)。所以大多數(shù)數(shù)據(jù)轉(zhuǎn)換軟件會簡單地忽略它們。如果處理指令和注釋對你相當重要,就要檢查所用軟件對此能否處理及處理方法?;蛘呖梢钥紤]使用原生XML數(shù)據(jù)庫(native XML database)。

5.4.6 對標記的存儲 (Storing Markup)
正如5.1.2 一節(jié)所提到的, 有時候需要在數(shù)據(jù)庫中存儲混合內(nèi)容的元素而無須進一步解析。這時,標記被存儲為標記字符(markup is stored with markup characters)。然而,問題出現(xiàn)在如何存儲那些不作為標記使用的標記字符。在XML文檔中,這些是以 lt, gt, amp, quot 和 apos 實體存儲的。在數(shù)據(jù)庫中也可這么做。例如,下面的description:

<description>
      <b>Confusing example:</b> <foo/>
   </description>
在數(shù)據(jù)庫中可存為:

<b>Confusing example:</b> <foo/>
這樣做的一個問題是一些非XML查詢語言,如SQL不會在表中搜尋標記和實體的用法并將其正確翻譯。這樣,如果你打算用SQL來搜索字符串“<foo/>”,你應(yīng)當知道實際的搜索字符串是“<foo/>”。 

另外,如果實體引用被擴展了,數(shù)據(jù)轉(zhuǎn)換軟件無法區(qū)別標記和實體。例如,如果上述例子在數(shù)據(jù)庫中按照下面的形式存儲,則軟件就無法知道<b> , </b> 和<foo/>到底是標記還是文本。 

  <b>Confusing example:</b> <foo/>解決這個問題的長久之計就是支持XML的數(shù)據(jù)庫(XML-aware database),在那里,對真正的標記和看起來很像標記的東西的處理方式是不同的。非XML應(yīng)用程序處理XML時,總是會出現(xiàn)這種問題。 

5.5 從關(guān)系[數(shù)據(jù)庫]Schema產(chǎn)生DTD或相反 (Generating DTDs from Relational Schema and Vice Versa)
在XML文件與數(shù)據(jù)庫之間進行數(shù)據(jù)轉(zhuǎn)換時經(jīng)常遇到的一個問題是如何從數(shù)據(jù)庫schema產(chǎn)生DTD或相反。在解釋如何做之前,必須指出這是設(shè)計階段的任務(wù)。其原因是大多數(shù)以數(shù)據(jù)為中心的應(yīng)用以及幾乎所有的盤點應(yīng)用軟件(vertical applications)都是在已知的DTD或數(shù)據(jù)庫模型上工作的,因此,不會在運行時產(chǎn)生schema。再者,如下所述,schema的產(chǎn)生過程不十分嚴格。如果應(yīng)用程序需要在數(shù)據(jù)庫中隨機存放XML文件,則應(yīng)考慮使用使用原生XML數(shù)據(jù)庫,而不是在運行時產(chǎn)生schema.

從DTD產(chǎn)生關(guān)系模型(或相反)的最簡單方法就是直接借助于對象-關(guān)系映射,它有幾個可選特性。對于面向?qū)ο蟮臄?shù)據(jù)庫也有相似的途徑。(關(guān)于每種方法的逐步演示,請看Mapping DTDs to Databases.)。 

從DTD產(chǎn)生關(guān)系模型: 

對每個復合數(shù)據(jù)類型, 創(chuàng)建一個表格和主鍵字段 
對每個混合內(nèi)容的元素類型,另外建一個表用來存儲PCDATA,通過其父表格的主鍵與父表格相連。 
對該種數(shù)據(jù)類型的每個單值屬性,以及每個單次出現(xiàn)簡單子元素在表中建一個字段。如果子元素或?qū)傩允强蛇x的,將該字段設(shè)置為可為空值的字段(nullable)。 
對每個多值屬性(multi-valued attribute)和每個多次出現(xiàn)的簡單元素,單獨創(chuàng)建一個表,通過其父表格的主鍵與父表格相連 
對每個復合類型的字元素,通過其父表格的主鍵將父表與該子元素類型的表相連。 
從關(guān)系[數(shù)據(jù)庫]模型產(chǎn)生DTD: 

為每個表創(chuàng)建一種元素類型。 
對表中的每個數(shù)據(jù)(非鍵)字段以及主鍵字段,在元素類型上增加一個屬性或在內(nèi)容模型上增加一個PCDADA型的字元素。 
對于每個引用該主鍵的表格,在內(nèi)容模型上增加一個子元素,繼續(xù)遞歸處理表格。 
對于每個外來鍵,在內(nèi)容模型上增加一個子元素,繼續(xù)遞歸處理外來鍵表格。 
這些過程有一些不足,其中許多都可手工解決,比如名稱沖突及指定字段數(shù)據(jù)類型和長度。(DTD不包含數(shù)據(jù)類型信息,所以不可能預知數(shù)據(jù)庫中的數(shù)據(jù)類型。注意,從XML Schema文件可以預測數(shù)據(jù)類型和長度。) 

更加嚴重的問題是,XML文件所用的數(shù)據(jù)“模型”通常和數(shù)據(jù)庫中所用的高效率的模型不同,(實際上更為復雜)。請看如下XML片斷: 

<Customer>
      <Name>ABC Industries</Name>
      <Address>
         <Street>123 Main St.</Street>
         <City>Fooville</City>
         <State>CA</State>
         <Country>USA</Country>
         <PostCode>95041</PostCode>
      </Address>
   </Customer>
從DTD產(chǎn)生關(guān)系模型的一般過程來看,通常會產(chǎn)生兩個表:一個是customers,另一個是addresses。然而,大多數(shù)情況下把 address存放在customer表中更為合理。

<Address>元素就是包裝元素(wrapper element)的典型例子。采用包裝元素的原因有二:首先,這種結(jié)構(gòu)使得文檔更容易理解;其次,它可作為一種數(shù)據(jù)類型使用。例如,可以將<Address>元素傳給一個例程,該例程可以將所有地址轉(zhuǎn)換為Address對象,不管它出現(xiàn)在哪里。 

雖然包裝元素在XML中很有用,但被映射到數(shù)據(jù)庫中的時候會增加額外的結(jié)構(gòu),很容易出問題。因此,在產(chǎn)生關(guān)系模型之前,一般應(yīng)將其從DTD中除去。由于DTD一般是不允許改變的,而在映射是又不包含包裝元素,所以往往會導致實際文檔與數(shù)據(jù)轉(zhuǎn)換軟件所要求的文檔不匹配。對此可以在運行時轉(zhuǎn)換文件(比如使用XSLT):數(shù)據(jù)被轉(zhuǎn)到數(shù)據(jù)庫之前去掉包裝元素,轉(zhuǎn)出后在加上它。 

盡管有這些不足,上述步驟還是為DTD和關(guān)系模型之間的轉(zhuǎn)換提供了一個起點,對于大型系統(tǒng)尤為如此。 

6.0 文件的存取 (Storing and Retrieving Documents)
XML文件的存儲方式有兩大類:存儲于文件系統(tǒng)或作為BLOB存儲于關(guān)系數(shù)據(jù)庫以獲得有限的XML功能,或者將其存儲于原生XML數(shù)據(jù)庫。 

6.1 將文件存儲于文件系統(tǒng) (Storing Documents in the File System)
如果你的文件比較簡單,數(shù)量不多,最簡便的方法就是存儲于文件系統(tǒng)。以后可以使用grep之類的工具進行查詢或sed來修改。(對XML文件進行全文檢索顯然不夠精確,比如很難區(qū)分文本和標記,而且無法理解實體的用法。然而,對于小型系統(tǒng),這還是可以接受的)如果你想實現(xiàn)簡單的事務(wù)管理(transaction control),可以將文件放在諸如CVS或RCS等版本管理系統(tǒng)中。 

6.2 將文件存儲于BLOB (Storing Documents in BLOBs)
另一種較為復雜的方法就是將文件存儲于關(guān)系數(shù)據(jù)庫中的BLOB。這就利用了數(shù)據(jù)庫的一些優(yōu)點:事務(wù)管理、安全、多用戶訪問等。此外許多關(guān)系數(shù)據(jù)庫提供的檢索工具可以進行全文檢索、近似檢索、同義詞檢索和模糊檢索。其中某些工具將會支持XML,這樣就可消除將XML文件作為純文本檢索所帶來的問題。

如果以BLOB的形式存儲XML文件,即使數(shù)據(jù)庫不支持對XML的檢索,你也很容易實現(xiàn)自己的XML檢索。方法之一是創(chuàng)建兩個表:索引表(DB2中的side table)和文件表。文件表包含一個主鍵和一個存儲文件的BLOB字段,索引表內(nèi)有一個已建立索引值字段以及一個外來鍵指向文件表中的主鍵。

文件被存在數(shù)據(jù)庫中之后,就可以搜索所有已建索引的元素和屬性實例。每個實例及文件的主鍵都存于索引表中。這樣已建立索引的字段使應(yīng)用程序可以快速檢索某個元素或?qū)傩灾挡@取相應(yīng)的文件。 

舉例來說,假如你有一些符合下列DTD的文件,希望建立作者的索引: 

<!ELEMENT Brochure (Title, Author, Content)>
   <!ELEMENT Title (#PCDATA)>
   <!ELEMENT Author (#PCDATA)>
   <!ELEMENT Content (%Inline;)> <!-- Inline entity from XHTML -->你可以用下表來存儲它: 

   Authors                     Brochures
   ----------------------      ---------
   Author     VARCHAR(50)      BrochureID INTEGER
   BrochureID INTEGER          Brochure   LONGVARCHAR假如你在數(shù)據(jù)庫中插入了一個brochure,程序就會在Brochures表中插入該 brochure,然后尋找<Author>元素,將它的值和brochure ID存入Authors表中。以后就可通過簡單的SELECT語句得到某個Author的所有brochure。比如想得到author為Chen的所有 brochure,就可以執(zhí)行下面的語句: 

   SELECT Brochure
   FROM Brochures
   WHERE BrochureID IN (SELECT BrochureID FROM Authors WHERE Author=‘Chen‘)
更復雜的索引表可包含四個字段:元素類型或?qū)傩悦?元素或?qū)傩?類型、值和文件ID。這樣就可在一個表中存放多個標記[文件], 并按名字、類型和值建立索引。寫個操作這個表的SAX程序應(yīng)該不是件難事。 

6.3 原生XML數(shù)據(jù)庫 (Native XML Databases)
上述的簡單系統(tǒng)所提供的功能如果不能滿足你的需要,你可以考慮使用原生XML數(shù)據(jù)庫(native XML database)。原生XML 數(shù)據(jù)庫是專用于存儲XML文件的數(shù)據(jù)庫。和其他數(shù)據(jù)庫一樣,它支持事務(wù)管理、安全、多用戶訪問、編程API和查詢語言等。與其它數(shù)據(jù)庫的唯一區(qū)別就是其內(nèi)部模型是基于XML的,而不是其他的模型--如關(guān)系模型。 

顯然原生XML數(shù)據(jù)庫最適于存儲以文檔為中心的文件。這是由于原生XML數(shù)據(jù)庫保留了文件[元素?]順序、處理指令、注釋、CDATA塊以及實體引用等,而支持XML的數(shù)據(jù)庫(XML-enabled database)無法做到。此外,原生數(shù)據(jù)庫支持XML查詢語言,你可以對它提這樣的問題:“找出所有第三段內(nèi)包含粗體字的文件”,用SQL顯然很難進行這樣的查詢。

原生XML數(shù)據(jù)庫還適用于存儲那些“天然格式”為XML的文件,而不管這些文件包含什么內(nèi)容。例如,電子商務(wù)系統(tǒng)消息所用的XML文件。盡管這些文件可能是以數(shù)據(jù)為中心的,而作為消息來說它們的天然格式是XML。這樣當它們被存入消息隊列后,建立在原生XML數(shù)據(jù)庫上的消息隊列使用起來更為方便。原生XML數(shù)據(jù)庫保留了XML的特性比如XML查詢語言,通常能更快地取出整條消息。Web cache是這類應(yīng)用的另一個例子。 

原生XML數(shù)據(jù)庫的其他用途是存儲半結(jié)構(gòu)化數(shù)據(jù)、在某種特定情形下提高存取速度以及存儲沒有DTD的文件(良構(gòu)的文件)。前兩種已經(jīng)在5.3 原生XML數(shù)據(jù)庫的數(shù)據(jù)存儲中敘述過。而后一種用非XML的數(shù)據(jù)庫是做不好的。也就是說,原生XML數(shù)據(jù)庫無須事先配置即可接受和存儲任何XML文件。將XML文件中的數(shù)據(jù)轉(zhuǎn)換到關(guān)系型或面向?qū)ο笮蛿?shù)據(jù)庫必須首先建立映射和數(shù)據(jù)庫模型。無須事先配置對于搜索引擎之類的應(yīng)用程序來說是有利的,因為沒有任何DTD能適用于所有搜索文檔。 

6.3.1 什么是原生數(shù)據(jù)庫(Native XML Database)?
"native XML database" 這個術(shù)語首先在 Software AG 為 Tamino 所做的營銷宣傳中露面。也許由于它的成功,后來這個術(shù)語在同類產(chǎn)品的開發(fā)商那里成了通用叫法。它是一個營銷術(shù)語,從來沒有正式的技術(shù)定義,這是它的一個缺陷。

有一個接近的定義(出自XML:DB mailing list的一個成員)這樣定義原生XML數(shù)據(jù)庫(native XML database): 

它為 XML 文檔(而不是文檔中的數(shù)據(jù))定義了一個(邏輯)模型,并根據(jù)該模型存取文件。這個模型至少應(yīng)包括元素、屬性、PCDATA 和文件順序。這種模型的例子有XPath數(shù)據(jù)模型、XML Infoset 以及 DOM 所用的模型和SAX 1.0的事件。

它以 XML 文件作為其基本(邏輯)存儲單位,正如關(guān)系數(shù)據(jù)庫以表中的行作為基本(邏輯)存儲單位。 
它對底層的物理存儲模型模型沒有特殊要求。例如,它可以建在關(guān)系型、層次型或面向?qū)ο蟮臄?shù)據(jù)庫之上,或者使用專用的存儲格式,比如索引或壓縮文件。 
該定義的第一部分與其他類型數(shù)據(jù)庫的定義相似,都是關(guān)于數(shù)據(jù)庫所用的模型的。不過,原生 XML 數(shù)據(jù)庫所能存儲的信息比模型中定義的多。例如,它可支持基于XPath 數(shù)據(jù)模型的查詢,但所用的存儲格式是純文本。CDATA 部分和實體用法也可存儲在數(shù)據(jù)庫中,但是模型中沒有包括。

定義的第二個部分是說原生數(shù)據(jù)庫的基本存儲單位是 XML 文件??雌饋硭坪跻部纱鎯?nbsp;XML 文件片斷,但幾乎所有的原生 XML 數(shù)據(jù)庫都是以文件方式存儲的。

(基本存儲單位就是可以容納一份數(shù)據(jù)的最低級的上下文 (context),相當于關(guān)系數(shù)據(jù)庫中的行。它的存在并不妨礙以更小的數(shù)據(jù)單位來讀取數(shù)據(jù),比如文件片斷或個別元素,同樣也不影響將不同文件中的片斷進行組合。從關(guān)系數(shù)據(jù)庫的術(shù)語來講,相當于數(shù)據(jù)雖然以行的形式存放,并不意味著無法讀取某個字段的值,或從現(xiàn)有的數(shù)據(jù)行創(chuàng)建新一行數(shù)據(jù)。)

該定義的第三部分講的是底層的數(shù)據(jù)存儲格式并不重要。確實如此,正如關(guān)系數(shù)據(jù)庫所使用的物理存儲格式與數(shù)據(jù)庫是不是關(guān)系型之間毫無關(guān)系。 

6.3.2 原生XML數(shù)據(jù)庫的結(jié)構(gòu) (Native XML Database Architectures)
原生XML數(shù)據(jù)庫的結(jié)構(gòu)可分為兩大類:基于文本的和基于模型的。

6.3.2.1 基于文本的原生XML數(shù)據(jù)庫(Text-Based Native XML Databases)
基于文本的原生XML數(shù)據(jù)庫將XML作為文本存儲。它可以是文件系統(tǒng)中的文件、關(guān)系數(shù)據(jù)庫中的BLOB或特定的文件格式。(事實上,就其能力來說,一個增加了支持CLOB(Character Large Object)字段的XML處理功能的關(guān)系數(shù)據(jù)庫也可以是原生XML數(shù)據(jù)庫了。)

索引對所有基于文本的原生XML數(shù)據(jù)庫來說都是一樣的,它可以使查詢引擎很方便地跳到XML文件內(nèi)的任何地方。這就可以大大提高數(shù)據(jù)庫存取文件或文件片斷的速度。這是因為數(shù)據(jù)庫只需進行一次檢索、磁頭定位,再假如所讀的文件在磁盤上是連續(xù)[存儲]的話,只需一次讀盤就可讀出整個文件或文件片斷。相反,如果像關(guān)系數(shù)據(jù)庫或基于模型的原生XML數(shù)據(jù)庫那樣,文件由各個部分組合而成,就必須要進行多次查找定位和多次讀盤動作。 

從這個意義上講,基于文本的原生XML數(shù)據(jù)庫與層次結(jié)構(gòu)的數(shù)據(jù)庫很相似,當存取預先定義好層次的數(shù)據(jù)的時候,它比關(guān)系數(shù)據(jù)庫更勝一籌。和層次結(jié)構(gòu)的數(shù)據(jù)庫一樣,當以其他形式比如轉(zhuǎn)置層次存取數(shù)據(jù)時,原生XML數(shù)據(jù)庫也會遇到麻煩。這個問題的嚴重程度尚未可知,很多關(guān)系數(shù)據(jù)庫都使用邏輯指針,使相同復雜度的查詢以相同的速度完成。由此看來這確實是個問題。 

6.3.2.2 基于模型的原生XML數(shù)據(jù)庫 (Model-Based Native XML Databases)
第二類原生XML數(shù)據(jù)庫是基于模型的原生XML數(shù)據(jù)庫。它們不是用純文本存儲文件,而是根據(jù)文件構(gòu)造一個內(nèi)部模型并存儲這個模型。至于模型究竟怎樣存儲取決于數(shù)據(jù)庫。有些數(shù)據(jù)庫將該模型存儲于關(guān)系型和面向?qū)ο蟮臄?shù)據(jù)庫中,例如在關(guān)系型數(shù)據(jù)庫中存儲DOM時,就會有元素、屬性、PCDATA、實體、實體引用等表格。其他數(shù)據(jù)庫使用了專為這種模型作了優(yōu)化的專有存儲格式。

(Mark Birbeck 在 1998年12月的 XML-L 郵件列表中描述了一個建立在關(guān)系型數(shù)據(jù)庫上的簡單的、基于 模型的原生 XML 數(shù)據(jù)庫系統(tǒng),該系統(tǒng)用了5個表 - 屬性定義、元素/屬性關(guān)聯(lián)、內(nèi)容模型定義、屬性值、元素值 (PCDATA 或指向其它元素的指針),以及只包含元素、屬性、文本和文件順序的模型。參見標題為 "Record ends, Mixed content, and storing XML documents on relational database" 和 "storing XML documents on relational database"的信件。)

建立在其他數(shù)據(jù)庫之上的基于模型的原生XML數(shù)據(jù)庫的文件存取性能與這些數(shù)據(jù)庫相似,原因顯而易見:其存取要依賴這些數(shù)據(jù)庫。但是這個數(shù)據(jù)庫,特別是建立在其他數(shù)據(jù)庫之上的原生XML數(shù)據(jù)庫的設(shè)計有很大的變化余地。例如直接以 DOM 方式進行對象-關(guān)系映射的數(shù)據(jù)庫系統(tǒng)在獲取節(jié)點的子元素時必須單獨執(zhí)行 SELECT 語句。另一方面,這種數(shù)據(jù)庫大多對存取模型和軟件作了優(yōu)化。例如 Richard Edwards 在 system for storing the DOM in a relational database一文中曾經(jīng)描述只用一個SELECT語句就可獲取任意文件片斷(或整個文件)。

使用專用存儲格式的基于模型的原生XML數(shù)據(jù)庫如果以文件的存儲順序讀取文件,其性能與基于文本的原生XML數(shù)據(jù)庫相似。這是因為這種數(shù)據(jù)庫大多在節(jié)點間使用了物理指針,這樣其讀取性能和讀取文本差不多。(究竟哪個快一些要取決于數(shù)據(jù)格式。如果返回文本格式,顯然基于文本的系統(tǒng)要快一些;如果希望返回的是DOM,假如該模型很容易映射到DOM,則基于模型的系統(tǒng)更快。) 

與基于文本的原生XML數(shù)據(jù)庫一樣,如果數(shù)據(jù)的讀取順序和存儲順序不同,基于模型的原生XML數(shù)據(jù)庫很容易出現(xiàn)性能上的問題。這兩種類型的數(shù)據(jù)庫到底哪個快一些仍不是很清楚。

6.3.3 原生XML數(shù)據(jù)庫的特性 (Features of Native XML Databases)
本節(jié)簡單討論原生XML數(shù)據(jù)庫的一些特性,有助于大致了解其現(xiàn)狀和未來。

6.3.3.1 文件集 (Document Collections)
許多原生XML數(shù)據(jù)庫都支持集合(collection)的概念,其作用相當于關(guān)系數(shù)據(jù)庫中的表和文件系統(tǒng)中的文件夾,例如你想在原生XML數(shù)據(jù)庫中存儲銷售訂單,就可以定義一個銷售訂單的集合,這樣對銷售訂單的查詢就限于這個集合內(nèi)的文件。 

作為另一個例子,假設(shè)你想把公司的所有產(chǎn)品的說明書存儲在原生XML數(shù)據(jù)庫中,在這種情形下,你要先定義一個層次結(jié)構(gòu)。比如,為每種產(chǎn)品定義一個集合,并在其中為每種產(chǎn)品說明書的每個章節(jié)都指定一個集合。 

這些集合是否被允許嵌套取決于所用的數(shù)據(jù)庫。 

6.3.3.2 查詢語言 (Query Languages)
幾乎所有的原生XML數(shù)據(jù)庫都至少支持一種查詢語言。最常用的有 XPath (對多個文件的查詢作了擴充)和 XQL,以及很多專有的查詢語言。在考慮原生XML數(shù)據(jù)庫時應(yīng)當確定其查詢語言是否滿足你的需要,比如從全文檢索到多個文件片斷的合并。 

將來大多數(shù)原生XML數(shù)據(jù)庫大概都要支持W3C的XQuery。 

6.3.3.3 更新和刪除 (Updates and Deletes)
原生XML數(shù)據(jù)庫對文件的更新和刪除方式有許多,從簡單的替換或刪除現(xiàn)有文件,到修改當前活動的 DOM 樹,以及用于指定如何修改文件片斷的語言。通常每種能修改文件片斷的產(chǎn)品都有自己的語言,盡管有幾種產(chǎn)品支持XML:DBInitiative 的XUpdate語言。至于文件的更新正是業(yè)界和學術(shù)界的探討領(lǐng)域,近期似乎沒有完整的解決方案[2002年2月]。 

6.3.3.4 事務(wù)、鎖定和并發(fā) (Transactions, Locking, and Concurrency)
基本上所有的原生XML數(shù)據(jù)庫都支持事務(wù)處理(當然也應(yīng)支持后退[rollback])。但是,鎖定通常是對整個文檔的而不是對文件片斷的,所以多用戶并發(fā)性[的支持]相對較低。問題的大小取決于應(yīng)用程序以及“文件”的構(gòu)成。 

例如用戶手冊分成幾個章節(jié),每個章節(jié)都是一個文件,這時并發(fā)問題就小一些,因為兩個作者同時對同一章節(jié)進行更新的情況不大可能發(fā)生。而另一方面,如果整個公司的客戶數(shù)據(jù)都放在同一個文件中(糟糕的設(shè)計),文件級的鎖定很容易造成災(zāi)難性的后果。 

將來,大多數(shù)的原生數(shù)據(jù)庫應(yīng)該會提供文件片斷級的鎖定。 

6.3.3.5 應(yīng)用程序接口 (Application Programming Interfaces ,APIs)
幾乎所有原生數(shù)據(jù)庫都提供編程接口API。這種API很像ODBC,并提供有連接到數(shù)據(jù)庫、瀏覽元數(shù)據(jù)、執(zhí)行查詢和返回結(jié)果的方法 (methods)。返回結(jié)果通常是XML字符串、DOM樹、返回文檔的SAX解析器或XMLReader。如果查詢返回結(jié)果是多個文檔的話,通常都會提供例舉(iterating)這些結(jié)果的方法。 

對以數(shù)據(jù)為中心的應(yīng)用來說比較有趣的特性是將應(yīng)用程序變量與返回文檔的特定元素或?qū)傩韵嚓P(guān)聯(lián)的能力。這就免除了應(yīng)用程序為構(gòu)件內(nèi)部數(shù)據(jù)對象而不得不對文檔進行解析的工作,隨著XML數(shù)據(jù)綁定技術(shù)的應(yīng)用越來越多,看起來這個特性會得到廣泛支持。 

雖然大多數(shù)原生XML數(shù)據(jù)庫都提供有自己的API,但是XML:DB.org已經(jīng)開發(fā)出一種與供應(yīng)商無關(guān)的XML數(shù)據(jù)庫API (vendor-neutral XML database API),許多原生XML數(shù)據(jù)庫已經(jīng)支持它,而且有些非原生的[XML]數(shù)據(jù)庫也可能支持。不管這個或其他的API是否會成為工業(yè)標準,此類API的廣泛采用最終是不可避免的。 

大多數(shù)原生數(shù)據(jù)庫還有將查詢結(jié)果通過 HTTP 返回的能力。 

6.3.3.6 “往返車票”(Round-Tripping)
原生XML數(shù)據(jù)庫的一個重要特性是它可以為XML文檔提供了“往返車票(round-trip)”。就是說你可以將XML文件存放在原生XML數(shù)據(jù)庫中,而且再取回“同樣的”文件。對于以文檔為中心的應(yīng)用程序來說非常重要,因為CDATA部分、實體用法、注釋和處理指令是這些文檔不可缺少的組成部分。特別是對于法律和醫(yī)學文件,按規(guī)定這些文檔必須要保持原樣。 

(對于以數(shù)據(jù)為中心的應(yīng)用來說,由于它主要關(guān)心的是元素、屬性、文本以及層次順序,這種“往返車票”顯得不是很重要。能夠在XML文件和數(shù)據(jù)庫之間交換數(shù)據(jù)的軟件都可以處理這些往返問題,如果同級元素的順序?qū)σ詳?shù)據(jù)為中心的應(yīng)用程序來說很重要,在有限幾種情況下也可以保留這種順序。但是由于它[指一般的交換軟件--譯者注]一般不保留兄弟元素的順序,也不確保原樣保持處理指令、注釋以及物理結(jié)構(gòu)(實體引用、CDATA等等),所以不適于以文檔為中心的應(yīng)用。) 

所有原生XML數(shù)據(jù)庫都能夠在元素、屬性、CDATA和文件順序的級別上為文件提供“往返車票”,至于究竟能達到什么程度取決于數(shù)據(jù)庫。一般來說,基于文本的原生XML數(shù)據(jù)庫能夠原樣存取XML文件,而基于模型的原生XML數(shù)據(jù)庫只能在文件模型的級別上原樣存取XML文件。對于特別小的文檔模型,意味著比普通的XML原樣存取的級別低。 

由于你的應(yīng)用程序要求決定了應(yīng)當在哪個級別原樣存取,所以對原生XML數(shù)據(jù)庫的選擇余地可能很大,也可能很小。 

6.3.3.7 外部數(shù)據(jù) (Remote Data)
某些原生XML數(shù)據(jù)庫可包含有外部數(shù)據(jù),這些外部數(shù)據(jù)來自存儲在數(shù)據(jù)庫中的文檔。通常這些數(shù)據(jù)通過ODBC、OLE DB或JDBC從關(guān)系數(shù)據(jù)中取出,模型可以是基于表格的或?qū)ο?關(guān)系型映射。原生XML數(shù)據(jù)庫決定了這些數(shù)據(jù)是不是即時的(live)--即原生XML數(shù)據(jù)庫中文檔的更新是否在外部數(shù)據(jù)庫中反映出來。大多數(shù)原生XML數(shù)據(jù)庫大概最終都會支持即時的外部數(shù)據(jù)。 

6.3.3.8 索引 (Indexes)
幾乎所有的原生XML數(shù)據(jù)庫都支持元素和屬性的索引。像非XML數(shù)據(jù)庫一樣,索引用于提高檢索速度。

6.3.3.9 外部實體存儲 (External Entity Storage)
XML文檔存儲時的一個棘手問題就是怎樣處理外部實體。也就是說,應(yīng)當將其展開,把它的值存儲在文件中,還是保留實體引用原封不動?這個問題沒有統(tǒng)一的答案。 

例如,假設(shè)文檔中包含一個外部實體用來調(diào)用一個當前天氣報告的CGI程序。如果將這個文件用于提供天氣預報的網(wǎng)頁,那么將這個實體展開就是錯誤的,因為網(wǎng)頁中提供的不是即時的數(shù)據(jù)。相反,如果文件是氣象歷史資料的一部分,那么不展開它反而是不對的,否則文件總是含有當前的數(shù)據(jù)而不是歷史資料了。 

再看另外一個例子,假設(shè)一個產(chǎn)品手冊只包含指向手冊中其他章節(jié)的外部實體引用。如果這些章節(jié)又被其他文件(比如該產(chǎn)品的另一種型號的手冊)使用,那么展開這些引用就不對了,因為這會造成同一個章節(jié)有多份拷貝。 

我不知道原生XML數(shù)據(jù)庫如何處理這個問題。最理想的當然是允許你根據(jù)不同情況指定是否展開外部實體引用。 

6.3.4 規(guī)范化,引用完整性和可伸縮性 (Normalization, Referential Integrity, and Scalability)
對許多人,特別是有關(guān)系型數(shù)據(jù)庫背景的人來說,由原生XML數(shù)據(jù)庫引發(fā)出不少爭論,特別是圍繞數(shù)據(jù)的存儲方面(相對于文檔而言)。這里我們就來討論這些話題。 

6.3.4.1 規(guī)范化 (Normalization)
規(guī)范化指的是數(shù)據(jù)庫模型的設(shè)計當中要保證每一份數(shù)據(jù)只能存儲一次。規(guī)范化有幾個好處,例如可以減少磁盤空間占用,消除可能的數(shù)據(jù)不一致性。這是關(guān)系型數(shù)據(jù)庫技術(shù)的基礎(chǔ)之一,也是人們在討論原生XML數(shù)據(jù)庫的數(shù)據(jù)存儲時的熱點問題。 

在進一步討論規(guī)范性之前,需要指出對許多以文檔為中心的文件這不是大問題。例如有一些描述公司產(chǎn)品信息的文件,通常各個文件的公用數(shù)據(jù)很少--比如版權(quán)聲明、公司地址和電話號碼、產(chǎn)品標志等等,其數(shù)量相對來說太小了,幾乎沒有人考慮它的存儲規(guī)范性。(但是,其他種類的文檔可能有許多重疊內(nèi)容,有必要進行規(guī)范化)。 

與關(guān)系型數(shù)據(jù)庫一樣,原生XML數(shù)據(jù)庫并不要求你一定要規(guī)范你的數(shù)據(jù),用原生XML數(shù)據(jù)庫你也很容易設(shè)計出一個糟糕的存儲結(jié)構(gòu)。所以在將文件存入原生XML數(shù)據(jù)庫之前,你應(yīng)仔細考慮文檔的結(jié)構(gòu)。(與關(guān)系型數(shù)據(jù)庫相比,原生XML數(shù)據(jù)庫在這點有些優(yōu)勢。因為原生XML數(shù)據(jù)庫沒有數(shù)據(jù)庫模式,你可以同時以多種模式存儲相似的文件,不過為了簡化事務(wù)處理,你可能需要重新設(shè)計查詢并轉(zhuǎn)換你的文件(這相對并不重要)) 

原生XML數(shù)據(jù)庫的規(guī)范化和關(guān)系型數(shù)據(jù)庫的規(guī)范化差不多一樣:你的文檔的設(shè)計要保證不會有重復數(shù)據(jù)。兩者的不同在于XML支持多值屬性而(大多數(shù))關(guān)系型數(shù)據(jù)庫不支持。這樣就有可能以一種在關(guān)系型數(shù)據(jù)庫中無法實現(xiàn)的方式來“規(guī)范”原生XML數(shù)據(jù)庫的數(shù)據(jù)。 

例如銷售訂單,它含有頭信息比如訂單編號、日期和客戶代碼,還有具體項目如零件號、數(shù)量和總價。在關(guān)系型數(shù)據(jù)庫中,頭信息和具體項目必須存在于不同的表內(nèi)。而在原生XML數(shù)據(jù)庫中,這些信息可以存儲在同一個文件內(nèi),不會產(chǎn)生冗余,因為XML與生俱來就支持一個父元素內(nèi)包含多個子元素。 

不幸的是,現(xiàn)實當中的規(guī)范化可沒這么簡單。例如你想要銷售訂單包含客戶信息如合同名稱、收貨和付款地址,該怎樣做? 你有兩種選擇:第一,你可以在銷售訂單中復制一份客戶信息,結(jié)果帶來數(shù)據(jù)冗余和其他問題;第二,你可以單獨存儲客戶信息,在銷售訂單中提供一個指向客戶信息文件的XLink,或者在查詢時再將這兩個文件連接起來。這就要求對XLink的支持(雖然正在計劃,但大多并不支持)或者查詢語言要支持聯(lián)合[joins](同樣并不總能如愿)。

在實踐當中答案尚不明確。實際當中出于性能的考慮,數(shù)據(jù)并不總是規(guī)范的,所以有一些不規(guī)范的XML數(shù)據(jù)并不像初看起來那么糟糕,不過你必須做出抉擇。如果你存儲的是以文檔為中心的文件并且在相當程度上做到了規(guī)范化,比如將章節(jié)或過程單獨存儲并將它們連接起來創(chuàng)建最終用戶所用的文件,那么原生XML數(shù)據(jù)庫可能就是一個不錯的解決方案,尤其是它能提供別的數(shù)據(jù)庫中所沒有的特性比如XML查詢語言。如果你要存儲的文件是以數(shù)據(jù)為中心的,而原生XML數(shù)據(jù)庫能夠改進應(yīng)用程序的性能,或者它提供的半結(jié)構(gòu)化數(shù)據(jù)存儲,而在別的數(shù)據(jù)庫中是無法實現(xiàn)的,你也應(yīng)當用原生XML數(shù)據(jù)庫。如果你只不過想在原生XML數(shù)據(jù)庫內(nèi)實現(xiàn)一個關(guān)系型數(shù)據(jù)庫,你就應(yīng)該反思一下,為什么不把關(guān)系型數(shù)據(jù)庫列為首選。 

6.3.4.2 引用完整性 (Referential Integrity)
與規(guī)范性密切相關(guān)的是引用完整性(referential integrity)。引用完整性即相關(guān)數(shù)據(jù)的[引用]指針的有效性,是保持數(shù)據(jù)庫數(shù)據(jù)一致性的必要條件。如果你的銷售訂單含有一個客戶代碼,而相應(yīng)的客戶信息并不存在,這對你沒什么好處。發(fā)貨部門不知道往哪里發(fā)貨,而財務(wù)部門不知道給哪里寄發(fā)票。 

在關(guān)系型數(shù)據(jù)庫中,引用完整性意味著確保外部鍵指向合法的主鍵,也就是說,對每個外部鍵都要檢查相應(yīng)的主鍵記錄。在原生XML數(shù)據(jù)庫中,引用完整性意味著XLink或其他專有鏈接機制指向合法的文件或文件片斷。

XML 文件中的指針有多種形式:ID/IDREF 屬性,key/keyref 域(在 XML Schema 中定義),XLink 以及各種私有機制。后者包括語言相關(guān)的“referencing”元素和屬性,例如 XML Schema 中 <element>元素的 ref 屬性,以及特定數(shù)據(jù)庫的鏈接機制。而語言相關(guān)的“referencing” 元素比較普遍,數(shù)據(jù)庫特定的鏈接機制較為少見。

原生 XML 數(shù)據(jù)庫的引用完整性可分為兩大類:內(nèi)部指針(同一文件內(nèi)的指針)的完整性和外部指針(不同文件之間的指針)的完整性。使用非標準機制實現(xiàn)的內(nèi)部指針的引用完整性一向難以達到,因為原生 XML 數(shù)據(jù)庫無法識別此類指針。以標準機制比如 ID/IDREF 或 key/keyref 實現(xiàn)的內(nèi)部引用完整性至少可通過驗證獲得部分支持。

之所以說部分支持,是因為大多數(shù)原生 XML 數(shù)據(jù)庫僅在將文件存入數(shù)據(jù)庫時才進行驗證。這樣,如果更新發(fā)生在文件級 - 即刪除和替換文件,驗證已足以確保內(nèi)部指針的完整性。但是如果更新發(fā)生在節(jié)點一級 -即插入、修改和刪除節(jié)點,則數(shù)據(jù)庫必須執(zhí)行額外的工作(比如校驗所有的變化)來確保內(nèi)部指針的引用完整性。支持該功能的原生 XML 數(shù)據(jù)庫極少(如果有的話)。

對外部指針的引用完整性(據(jù)我所知)仍未有支持,甚至支持外部指針的數(shù)據(jù)庫都很罕見。假如某個外部指針指向了數(shù)據(jù)庫中的其他資源,沒有理由不保證其完整性,但如果指向了數(shù)據(jù)庫之外的資源,這種保證的缺乏尚有情可原。例如,某個文件內(nèi)的一個 XLink 指向了外部網(wǎng)站的某個文件,數(shù)據(jù)庫顯然無法知道后者是否存在,因而也就無法保證該 XLink 的完整性。

將來,許多原生XML數(shù)據(jù)庫大致都會以標準的機制支持內(nèi)部指針的引用完整性。許多原生 XML數(shù)據(jù)庫大約都會在某種程度上支持外部指針,以及支持指向同一個數(shù)據(jù)庫中的資源的外部指針的引用完整性。而在目前,多數(shù)情況下還有賴于應(yīng)用程序保證(內(nèi)部或外部)指針的完整性。

6.3.4.3 可伸縮性 (Scalability)
可伸縮性完全不是我的所長,所以下面大多都是我的推測??偟膩碚f,我想原生XML數(shù)據(jù)庫的可伸縮性在某些環(huán)境下會非常好,而其他場合下可能非常糟糕。 

與層次型和關(guān)系型數(shù)據(jù)庫類似,原生XML數(shù)據(jù)庫也使用索引來查找數(shù)據(jù)。這就意味著文件(或文件片斷)的查找只與索引的大小有關(guān),而與文件的大小和數(shù)量無關(guān),因而原生XML數(shù)據(jù)庫定位文件開始的速度和其他使用同一種索引技術(shù)的數(shù)據(jù)庫一樣。由此看來,原生XML數(shù)據(jù)庫的可伸縮性和其他數(shù)據(jù)庫一樣。 

與層次型數(shù)據(jù)庫相同而與關(guān)系型數(shù)據(jù)庫不同的是,許多原生XML數(shù)據(jù)庫用物理方法鏈接相關(guān)數(shù)據(jù)。特別是基于文本的原生XML數(shù)據(jù)庫用物理的方法對相關(guān)數(shù)據(jù)分組,使用專用存儲格式的基于模型的原生XML數(shù)據(jù)庫通常使用物理指針來對相關(guān)數(shù)據(jù)分組。(建立在關(guān)系數(shù)據(jù)庫之上基于模型的原生XML數(shù)據(jù)庫使用的是邏輯鏈接。) 

由于物理鏈接比邏輯鏈接速度快,原生XML數(shù)據(jù)庫和層次型數(shù)據(jù)庫一樣,數(shù)據(jù)的讀出速度比關(guān)系型數(shù)據(jù)庫快得多。因此,從數(shù)據(jù)的讀取方面來看,它應(yīng)具有同樣的可伸縮性。事實上,在數(shù)據(jù)的讀取能力上XML數(shù)據(jù)庫比關(guān)系型數(shù)據(jù)庫甚至更好,因為可伸縮性與初次索引查找有關(guān),而不是關(guān)系型數(shù)據(jù)庫所用的多次查找。(需要指出,關(guān)系型數(shù)據(jù)庫也以集簇索引(clustered indexes)的形式提供數(shù)據(jù)的物理鏈接。不過,這種鏈接是應(yīng)用于各個表格而不是整體層次上的。) 

令人遺憾的是這種可伸縮性是有限的。就像層次型數(shù)據(jù)庫,原生XML數(shù)據(jù)庫中所用的物理連接只能作用于特定的層次。也就是說,如果數(shù)據(jù)的讀取和數(shù)據(jù)的存儲在同一層次下,則讀取速度很快,否則就不一定快。例如將客戶信息存儲在各個銷售訂單文件中,則讀取銷售訂單時的速度很快,而如果需要的數(shù)據(jù)視圖不同,比如要找出某個客戶的所有訂單將會很慢,因為此時物理連接已不再適用。) 

為了緩解這個問題,原生XML數(shù)據(jù)庫大量使用了索引,經(jīng)常對所有元素和屬性都作了索引。這雖然有助于減少讀取時間,卻增加了更新時間,因為維護這種索引的代價很高。在只讀的環(huán)境下這無關(guān)緊要,在交易頻繁的環(huán)境下可能造成麻煩。 

最后,對于未索引數(shù)據(jù)的查找來說,原生XML數(shù)據(jù)庫的可伸縮性比關(guān)系型數(shù)據(jù)庫差的多。此時這兩種數(shù)據(jù)庫都要線性地查找數(shù)據(jù),而原生XML數(shù)據(jù)庫的情況更為糟糕,因為它的數(shù)據(jù)不是完全規(guī)范的。比如你要查找某個日期的所有銷售訂單,而日期是未經(jīng)索引的。如果用的是關(guān)系型數(shù)據(jù)庫,就要讀取所有OrderDate字段的值,而對于原生XML數(shù)據(jù)庫,這意味著要讀取每個銷售訂單文件,并從中查找<OrderDate>元素。不但需要讀取<OrderDate>元素的內(nèi)容;而且還要讀取所有其它文件的內(nèi)容。對于基于文本的原生XML數(shù)據(jù)庫,情況也很不妙:在與目標日期比較之前,必須先對文本進行解析并轉(zhuǎn)換為日期格式。 

那么對你來說,可伸縮性是否嚴重?這完全取決于你的應(yīng)用。如果你的應(yīng)用程序中所需的數(shù)據(jù)一般都和其存儲形式相同,則原生XML數(shù)據(jù)庫的可伸縮性應(yīng)是不錯的。許多以文本為中心的應(yīng)用就屬于這種情形。例如組成產(chǎn)品手冊的文檔幾乎總是作為整體讀取的。反之,如果你的應(yīng)用中數(shù)據(jù)視圖不是很確定,則可伸縮性有可能出問題。 

對于原生XML數(shù)據(jù)庫的討論就到此結(jié)束。在接下來的兩部分中,我們將考察兩種特殊的原生XML數(shù)據(jù)庫:可持久化DOM和內(nèi)容管理系統(tǒng)。 

6.3 可持久化DOM (Persistent DOMs, PDOMs)
可持久化DOM(persistent DOM)或PDOM是在某種持久性存儲[介質(zhì)]上實現(xiàn)了DOM 的一種特殊的原生XML數(shù)據(jù)庫。與大多數(shù)以DOM樹返回文檔的原生XML數(shù)據(jù)庫不同,PDOM返回的DOM是實時的(live)。也就是說,對DOM所作的改變直接反映在數(shù)據(jù)庫中。(這種改變實際上是否馬上做出或者通過調(diào)用一個方法來實現(xiàn)取決于數(shù)據(jù)庫)大多數(shù)原生XML數(shù)據(jù)庫返回個應(yīng)用程序的DOM樹是一個復制品,而數(shù)據(jù)庫中的改變是通過XML更新語言,或者是通過替換整個文件來實現(xiàn)的。 

由于PDOM樹是實時的,數(shù)據(jù)庫通常是在本地。這就是說,它和應(yīng)用程序在同一個進程空間,或者至少在同一部機器(盡管這并不是必需的)。這是出于性能上的考慮,因為外部數(shù)據(jù)庫上的PDOM必須經(jīng)常向遠程服務(wù)器發(fā)出請求。 

PDOM在DOM應(yīng)用程序中所起的作用和在面向?qū)ο蟮膽?yīng)用程序中面向?qū)ο蟮臄?shù)據(jù)庫的作用一樣:它為應(yīng)用程序的數(shù)據(jù)提供了可持久化的存儲,也可作為應(yīng)用程序的虛擬內(nèi)存。后一種作用對于操作大型文件的DOM應(yīng)用來說有著特殊的重要性,因為DOM與XML文件長度之比很容易超過10。(實際的系數(shù)取決于文件中文本的平均長度,文本的平均長度較小的文件其系數(shù)較高。) 

6.4 內(nèi)容管理系統(tǒng) (Content Management Systems)
內(nèi)容管理系統(tǒng)是原生XML數(shù)據(jù)庫的另一種特殊形式。它們是為管理手工寫成的文件例如用戶手冊和技術(shù)草稿(white paper)而專門設(shè)計的,并且建立在原生XML數(shù)據(jù)庫之上。這個數(shù)據(jù)庫一般是處于用戶看不到的后臺,而提供給用戶的功能有:

版本和訪問控制。 
搜索引擎。 
XML/SGML編輯器。 
發(fā)布引擎。比如以書面、CD形式或在Web上發(fā)布。 
內(nèi)容與樣式的分離。 
可通過腳本或編程擴展。 
數(shù)據(jù)庫數(shù)據(jù)的集成(integration)。 
相對于文件管理系統(tǒng),內(nèi)容管理系統(tǒng)這個術(shù)語道出了這樣的事實:它使你可以將文件分為離散的片斷(比如示例、過程、章節(jié)或旁注)和元數(shù)據(jù)(例如作者、修訂日期、文件編號),而不是以整體管理文件。這不但簡化了一個文件多個作者時的協(xié)調(diào)工作,而且能使你從現(xiàn)有文件部分組合成全新的文件。

7.0 XML 數(shù)據(jù)庫產(chǎn)品 (Database Products)
關(guān)于最新的XML數(shù)據(jù)庫產(chǎn)品,參見XML Database Products.

8.0 相關(guān)鏈接 (Additional Links)
有關(guān)XML/數(shù)據(jù)庫的相關(guān)資源,包括軟件和文章,參見XML / Database Links。

9.0 意見和反饋 (Comments and Feedback)
請將意見和反饋發(fā)送給Ronald Bourret rpbourret@rpbourret.com。我經(jīng)常外出旅行,有可能延誤兩到三個星期。 

感謝Michael Champion, John Cowan, Marc Cyrenne, Marc de Graauw, Kelvin Ginn, Ingo Macherius, Lars Martin, Nick Leaton, Evan Lenz, Michael Rys, Walter Perry, Kimbro Staken, Jim Tivy, Phillipe Vauclair, Dylan Walsh, Irsan Widarto, Morten Primdahl 及其他人的意見和耐心。 

本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
四個主流的Native-XML數(shù)據(jù)庫
理解XML數(shù)據(jù)庫
XML數(shù)據(jù)庫問答 - JUST ON MY WAY
XML解析 DOM(文檔對象模型)與 SAX(XML簡易應(yīng)用應(yīng)用程序編程接口)_VICTO...
(轉(zhuǎn)變思路)如何將xml格式轉(zhuǎn)化為kml格式?
基于XML的知識管理系統(tǒng)
更多類似文章 >>
生活服務(wù)
分享 收藏 導長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服