Wolfgang Meier 的開(kāi)放源碼的 eXist 數(shù)據(jù)庫(kù)可能是當(dāng)今最流行的原生 XML 數(shù)據(jù)庫(kù)(但這并不是說(shuō)它是最好的)。eXist 是用 Java? 編程語(yǔ)言編寫(xiě)的,可運(yùn)行在大多數(shù)主要平臺(tái)上。程序通過(guò) eXist 綁定的 HTTP 服務(wù)器與 eXist 交互。SOAP、XML-RPC 和 RESTful 接口它都提供了,您可以通過(guò)這些接口向核心服務(wù)器提交 XPath、XQuery 和 XUpdate 請(qǐng)求。命令行和 GUI 客戶(hù)機(jī)也是可用的。
eXist 需要 Java 1.4 或更高版本,否則,所有必需的依賴(lài)關(guān)系都將被綁定。事實(shí)上,對(duì)于服務(wù)器端開(kāi)放源碼項(xiàng)目來(lái)說(shuō),安裝 eXist 已經(jīng)是相當(dāng)容易了。其他很多項(xiàng)目,不管是開(kāi)放源碼的,還是非開(kāi)放源碼的,安裝時(shí)都可以從安裝 eXist 受到啟發(fā)。安裝程序是用 IzPack 構(gòu)建的。發(fā)行版是一個(gè) JAR 檔案文件。要安裝 eXist,只要像下面這樣運(yùn)行該檔案文件即可:
|
安裝程序打開(kāi)一個(gè) GUI,詢(xún)問(wèn)您要將 eXist 目錄安裝在哪里。我把它安裝在 /home/elharo/eXist 中。eXist/bin 目錄包含必需的啟動(dòng)腳本。要啟動(dòng)服務(wù)器,可執(zhí)行 startup.sh (UNIX?) 或 startup.bat (Microsoft? Windows?):
|
該命令在端口 8080 上運(yùn)行服務(wù)器,并開(kāi)始服務(wù) /eXist 中的文件。您可以從任何 Web 瀏覽器連接到 eXist。例如,我將 eXist 安裝在 eliza.elharo.com 上,所以我可以在以下 URL 處連接到 eXist:
|
(您不要在自己家里這么去嘗試,因?yàn)槲业姆阑饓?huì)擋住您。您必須連接到您自己的服務(wù)器。)
最初,您將看到 eXist 文檔,還有一些您將要去探明的示例。
![]() ![]() |
![]()
|
eXist 不是真正的 Web 服務(wù)器,它只是使用一個(gè) Web 服務(wù)器作為到底層數(shù)據(jù)庫(kù)服務(wù)器的方便的接口。軟件包中還包含獨(dú)立的 GUI 客戶(hù)機(jī)和編程 API,您可以使用這些來(lái)執(zhí)行各種操作。您甚至可以使用 WebDAV 從 Microsoft Windows Explorer 瀏覽 eXist。對(duì)于初次體驗(yàn)來(lái)說(shuō),可能使用簡(jiǎn)單的 GUI 客戶(hù)機(jī)是最容易的。要啟動(dòng)客戶(hù)機(jī),可從 eXist/bin 目錄執(zhí)行 client.sh (UNIX) 或 client.bat (Windows):
|
從圖 1 可以看到,默認(rèn)情況下,客戶(hù)機(jī)試圖連接到運(yùn)行在端口 8080 上的本地主機(jī)上的 eXist 數(shù)據(jù)庫(kù)。您可以在 URL text 字段指定另外的主機(jī)和端口。這一個(gè)窗口也會(huì)要求輸入用戶(hù)名和密碼。默認(rèn)情況下,用戶(hù)名是 admin,可以將 password 字段保持為空。
圖 1. 連接到 eXist

![]() |
|
您登錄之后,客戶(hù)機(jī)顯示圖 2 所示的 GUI。最初,eXist 帶有一個(gè)集合,叫做 system,其中存儲(chǔ)有用戶(hù)信息。現(xiàn)在您不想使用這個(gè)集合,而是通過(guò)選擇 File > New Collection 為文檔創(chuàng)建一個(gè)新的集合。我創(chuàng)建了一個(gè)名為 books 的集合。要打開(kāi)集合,可在 GUI 中雙擊它。打開(kāi)一個(gè)集合后,要上載文檔,可單擊看起來(lái)有點(diǎn)像一張彎曲的紙、旁邊有一個(gè)加號(hào)的圖標(biāo)。
圖 2. eXist 管理客戶(hù)機(jī)

我首先上載兩個(gè)小文檔,數(shù)據(jù)庫(kù)毫無(wú)意見(jiàn)地接受它們。然后我嘗試上載我的 Processing XML with Java 一書(shū)的完整文本。這個(gè)操作悄無(wú)聲息地失敗了,沒(méi)有給出任何錯(cuò)誤消息。不通過(guò) GUI 客戶(hù)機(jī)上載,改為通過(guò) Web 接口上載也失敗了。但是該接口給出了一個(gè)堆棧跟蹤,有助于調(diào)試問(wèn)題。這表明 eXist 沒(méi)有解析文檔類(lèi)型聲明中使用的相對(duì) URL。要裝載具有外部 DTD 子集的文檔,您必須手動(dòng)在服務(wù)器的文件系統(tǒng)上安裝 DTD,并編輯一個(gè)編目文件,告訴數(shù)據(jù)庫(kù)要裝載的文檔在哪里;然后,必須重啟數(shù)據(jù)庫(kù)服務(wù)器,使它重新裝載編目文件。這是一個(gè)主要的爭(zhēng)論點(diǎn),盡管每個(gè)不同的 DTD 您通常只需要安裝一次。在您的文檔不使用 DTD 或者只使用少量不怎么改變的 DTD 時(shí),eXist 工作得最好。
![]() ![]() |
![]()
|
eXist 支持 XPath 和 XQuery(關(guān)于二者的更多信息,請(qǐng)參見(jiàn) 參考資料)。eXist 使用 2003 年 11 月 XQuery 工作草案中的 XQuery 語(yǔ)法。現(xiàn)在正在努力將數(shù)據(jù)庫(kù)更新到使用更多近期工作草案中的語(yǔ)法。對(duì)于基本的 For-Let-Where-Order-Return (FLWOR) 查詢(xún)來(lái)說(shuō),草案之間的差別并不大。
要輸入針對(duì)集合的查詢(xún),單擊 GUI 客戶(hù)機(jī)中的望遠(yuǎn)鏡圖標(biāo)以顯示圖 3 所示的窗口。
圖 3. eXist 查詢(xún)窗口

煩人的是,復(fù)制和粘貼在該界面中不起作用,所以必須手動(dòng)地鍵入所有查詢(xún)。當(dāng)然,這個(gè)程序只是用于測(cè)試和體驗(yàn),不能用它來(lái)與諸如 Oracle 這樣的您必須在其中鍵入原始 SQL 的數(shù)據(jù)庫(kù)進(jìn)行頻繁的交互。在對(duì)想要運(yùn)行的查詢(xún)有了相當(dāng)好的主意之后,您就可以編寫(xiě)程序根據(jù)算法來(lái)生成和提交查詢(xún),這一點(diǎn)我下面就會(huì)討論到。
![]() ![]() |
![]()
|
IBM?、Oracle 和 JSR 225 專(zhuān)家組的其他成員當(dāng)前正在定義一個(gè)用于取代 XQuery 的 API,其中 XQuery 由 JDBC 用于取代 SQL。但是直到這個(gè)過(guò)程結(jié)束并在 eXist 中實(shí)現(xiàn)該 API,仍然有必要使用 eXist 的本機(jī) API。您可以通過(guò) SOAP、XML-RPC、WebDAV 或 HTTP 接口訪(fǎng)問(wèn)這個(gè) API。任何支持這些協(xié)議之一的 API 都可以與 eXist 通信。例如,可以使用 JAX-RPC、通過(guò) SOAP 與 eXist 通信,或者使用 java.net、通過(guò) HTTP 與它通信。
RESTful HTTP 接口是最簡(jiǎn)單的,并且是這些選項(xiàng)中最廣泛可用的。例如,假設(shè)您想要找到包含單詞 “XSLT” 的 books 集合中的所有 para
元素。清單 1 中的 XQuery 找到所有這樣的元素。
清單 1. 一個(gè)示例 XQuery
|
您從下面這個(gè) URL 獲得(GET
)該查詢(xún):
|
其中 eliza.elharo.com
是網(wǎng)絡(luò)主機(jī),數(shù)據(jù)庫(kù)就運(yùn)行在它上面;8080
是端口;/exist/servlet/db
分別識(shí)別 Web 應(yīng)用程序、servlet 和數(shù)據(jù)庫(kù);books
是您在該數(shù)據(jù)庫(kù)查詢(xún)的特定集合。eXist 允許嵌套的集合。例如,books 集合可能包含單獨(dú)的小說(shuō)和非小說(shuō)集合,這些集合可在下面這些 URL 處得到:
|
然而對(duì)本文來(lái)說(shuō),您想要查詢(xún)所有的書(shū)籍,包括小說(shuō)和非小說(shuō)。XQuery 被作為 URL 的查詢(xún)字符串(URL 中引號(hào)后的部分)中的 _query
字段的值發(fā)送。它必須以通常方式用百分比編碼(例如,空格成了 %20
,雙引號(hào)成了 %22
,等等)。因此,您可以通過(guò)獲得(GET
)下面這個(gè) URL 將清單 1 中的查詢(xún)發(fā)送到服務(wù)器:
|
服務(wù)器將查詢(xún)結(jié)果封裝在 exist:result
元素中之后發(fā)送回來(lái),如清單 2 所示。
清單 2. 示例查詢(xún)的結(jié)果
|
其他可選查詢(xún)字符串變量控制結(jié)果是否是良好打印格式的、用什么元素封裝結(jié)果、返回多少匹配的值(默認(rèn)情況下,eXist 只返回前 10 個(gè)匹配的值),等等。
由于這全是通過(guò) HTTP GET
完成的,所以您可以簡(jiǎn)單地通過(guò)在 Web 瀏覽器中鍵入適當(dāng)?shù)?URL 而執(zhí)行該查詢(xún)。當(dāng)然,任何通過(guò) HTTP 傳遞信息的軟件庫(kù)也可以發(fā)送該查詢(xún)并取回 XML 流形式的結(jié)果。若要用 Java 語(yǔ)言來(lái)編寫(xiě)該查詢(xún),您可以使用 URLEncoder
類(lèi)來(lái)編碼查詢(xún)字符串,用 URL
來(lái)提交查詢(xún),并用 XOM 來(lái)處理結(jié)果,如清單 3 所示。
清單 3. 用 Java 代碼查詢(xún) eXist
|
像這樣的 HTTP 接口是完全語(yǔ)言獨(dú)立的。您可以容易地用 Perl、Python、C、C# 或任何其他具有一個(gè)簡(jiǎn)單 HTTP 庫(kù)和一些 XML 支持的語(yǔ)言重新產(chǎn)生清單 3 中的功能。查詢(xún)這樣的數(shù)據(jù)庫(kù)最有效的一種方式是編寫(xiě)一個(gè) XSLT 樣式表來(lái)格式化結(jié)果。
XQuery 允許您從數(shù)據(jù)庫(kù)取出信息。但是放入數(shù)據(jù)呢?這甚至更加容易。不是發(fā)送 GET
請(qǐng)求,而是發(fā)送 PUT
請(qǐng)求。放入(PUT
)數(shù)據(jù)到其中的 URL 就是文檔將要放入數(shù)據(jù)庫(kù)中的 URL;請(qǐng)求的主體是將要存儲(chǔ)的文檔。例如,清單 4 中的 Java 代碼從 Cafe con Leche Web 站點(diǎn)取得 RSS 提要,并將它放入名為 20050401 的聯(lián)合集合中。
清單 4. 用 Java 代碼將文檔插入 eXist 中
|
將新文檔放入數(shù)據(jù)庫(kù)中(PUT
)通常需要認(rèn)證。eXist 的 REST 接口支持 HTTP Basic 認(rèn)證。Java 語(yǔ)言通過(guò) java.net.Authenticator
類(lèi)支持這種認(rèn)證。本文不做詳細(xì)討論,但是簡(jiǎn)要來(lái)說(shuō),您必須用一個(gè)知道(或者知道如何詢(xún)問(wèn))數(shù)據(jù)庫(kù)用戶(hù)名和密碼的類(lèi)來(lái)繼承 Authenticator
,然后安裝該子類(lèi)的的一個(gè)實(shí)例作為系統(tǒng)默認(rèn)的認(rèn)證程序(authenticator)。
需要從集合中刪除文檔嗎?只要發(fā)送一個(gè) DELETE
請(qǐng)求到適當(dāng)?shù)?URL 即可,如清單 5 所示。
清單 5. 刪除 eXist 中的一個(gè)文檔
|
同樣,在實(shí)踐中也需要通過(guò)一個(gè) Authenticator
對(duì)象提供用戶(hù)名和密碼。
最后也是最復(fù)雜的操作是修改數(shù)據(jù)庫(kù)中的信息。例如,假設(shè)我要將 e-mail 地址從 elharo@metalab.unc.edu 更改為 elharo@macfaq.com。因此,我想要將所有的 <email>elharo@metalab.unc.edu</email>
元素更改為 <email>elharo@macfaq.com</email>
。XQuery 不提供這種能力,所以 eXist 使用 XUpdate 來(lái)代替。清單 6 中的 XUpdate 查詢(xún)作出了更改。
清單 6. 使用 XUpdate 來(lái)更新 eXist 中的文檔
|
由于該操作改變了一個(gè)資源,所以您需要使用 POST
方法來(lái)將它發(fā)送到服務(wù)器。您發(fā)出想要更改的文檔的 URL 并在請(qǐng)求體中給出 XUpdate 指令。
我只介紹了 REST 接口的要點(diǎn)。它也包含以下用途的指令:創(chuàng)建和刪除集合、指定查詢(xún)結(jié)果如何被格式化,以及提供用戶(hù)憑證。HTTP 也不只是 eXist 的接口。eXist 還具有針對(duì) Perl、PHP 和 Java 語(yǔ)言的本機(jī) API,以及一般的 WebDAV、SOAP 和 XML-RPC 接口。廣泛的 API 支持是 eXist 一個(gè)特別的優(yōu)點(diǎn)。
![]() ![]() |
![]()
|
eXist 并不是世界上最快的數(shù)據(jù)庫(kù)。您可以容易地使用一個(gè)秒表來(lái)度量它裝載一個(gè)中等大小的文檔所需的時(shí)間,即使在連接到本地?cái)?shù)據(jù)庫(kù)的快速硬件上也要花很長(zhǎng)的時(shí)間。查詢(xún)速度類(lèi)似于質(zhì)量。在比較大的集合上進(jìn)行復(fù)雜的查詢(xún)讓您有時(shí)間去煮一杯咖啡。為了縮短文檔裝載和查詢(xún)時(shí)間,您可以給 eXist 更多的內(nèi)存。與 eXist 一起發(fā)布的默認(rèn)配置指定的設(shè)置適合于具有 256 MB 左右內(nèi)存的機(jī)器。如果具有一臺(tái)比較強(qiáng)大的服務(wù)器,您可以修改 conf.xml file 給 eXist 分配更多的內(nèi)存。
為了優(yōu)化數(shù)據(jù)庫(kù),您可以添加索引。默認(rèn)情況下,eXist 對(duì)元素和屬性節(jié)點(diǎn)以及文檔的全部文本做索引。您可以為可能出現(xiàn)在您的查詢(xún)中的特定節(jié)點(diǎn)集指定附加的范圍索引。例如,如果您知道自己可能執(zhí)行大量的查找 para
元素的查詢(xún),那么可以在 //para
上定義一個(gè)查詢(xún)。這告訴 eXist 預(yù)先執(zhí)行和存儲(chǔ)文檔中所有 para
元素的值,因?yàn)樗鼈兒芸赡芎竺鏁?huì)用到。
因此,eXist 主要適合于速度不是很重要的小型集合。如果您具有千兆字節(jié)大小的文檔或者每小時(shí)要處理數(shù)千個(gè)事務(wù),那么請(qǐng)尋求別的辦法。
同樣,我不能保證我的數(shù)據(jù)對(duì) eXist 有效。我自己沒(méi)有體驗(yàn)過(guò)數(shù)據(jù)破壞。但是其他開(kāi)發(fā)人員會(huì)經(jīng)常遇到并修復(fù)數(shù)據(jù)庫(kù)破壞問(wèn)題。從正面來(lái)說(shuō),eXist 使得備份數(shù)據(jù)庫(kù)非常容易。非常重要的是,備份格式以真正的文本 XML 保存內(nèi)容,而不是以專(zhuān)有的二進(jìn)制格式保存;這意味著哪怕出現(xiàn)問(wèn)題,您可以用文本編輯器來(lái)修復(fù)。如果您經(jīng)常做歸檔備份,那么 eXist 的數(shù)據(jù)就不可能變得不可檢索。
eXist 功能恰當(dāng),能滿(mǎn)足一些基本的需求,并包含一些意想不到的附帶特性,比如 XInclude 支持。事務(wù)、回滾、撤退以及一些類(lèi)似的企業(yè)級(jí)特性都沒(méi)有包括(事務(wù)列在 “即將實(shí)現(xiàn)” 的清單內(nèi));但是許多應(yīng)用程序并不需要這類(lèi)高級(jí)功能。
我對(duì) eXist(就這一點(diǎn)來(lái)說(shuō),或者是任何其他基于 XQuery 的原生 XML 數(shù)據(jù)庫(kù))最關(guān)心的一點(diǎn)是底層標(biāo)準(zhǔn)和 API 的穩(wěn)定性。本文基于 eXist 的最新 beta 版,該版本基于 2003 年 11 月的 XQuery 草案、于 2004 年 11 月發(fā)布。eXist 的這個(gè)版本現(xiàn)在 CVS 中,作了一些向后不兼容的更改,這些更改還沒(méi)有完全文檔化。將來(lái)還會(huì)作更多的更改,不論是 eXist 中,還是它所依賴(lài)的 W3C 規(guī)范都會(huì)發(fā)生更改。除非您適應(yīng)那些需要您重新測(cè)試和編寫(xiě)代碼的頻繁更改,否則不要將 eXist 用于生產(chǎn)環(huán)境。
![]() ![]() |
![]()
|
擁有的數(shù)據(jù)越多,越需要使用數(shù)據(jù)庫(kù)系統(tǒng)來(lái)管理數(shù)據(jù)。如果數(shù)據(jù)是 XML,那么穩(wěn)定的原生 XML 數(shù)據(jù)庫(kù)無(wú)疑是適當(dāng)?shù)倪x擇。eXist 是一種穩(wěn)定的系統(tǒng)嗎?很遺憾,答案是否定的。eXist 是一個(gè)有趣的研究項(xiàng)目,也許會(huì)在一兩年內(nèi)開(kāi)發(fā)成一款有用的工具。但是就其當(dāng)前狀態(tài)來(lái)說(shuō),我無(wú)法推薦您使用它。文檔是不完整的,并且經(jīng)常會(huì)引起誤解。沒(méi)有錯(cuò)誤消息(各地的程序員請(qǐng)注意,異常堆棧跟蹤不能當(dāng)作真正的錯(cuò)誤消息,有時(shí),eXist 甚至連堆棧跟蹤都沒(méi)有提供給您)。GUI 時(shí)常會(huì)違反用戶(hù)界面標(biāo)準(zhǔn)。像復(fù)制和粘貼這樣的基本特性被忽略了。在為本文做非常基本的測(cè)試期間,我遇到了多個(gè) bug。
eXist 還沒(méi)有最終完成,當(dāng)前還處于 beta 版本。在版本 1.0 發(fā)布之前,我遇到的許多問(wèn)題都有望被解決,但不可能在短期內(nèi)解決。我知道現(xiàn)在就有一些人將 eXist 用于實(shí)際的工作,這讓我有些想不通。要么就是他們非常幸運(yùn),要么就是他們仔細(xì)地編寫(xiě)查詢(xún)和文檔,避免了 eXist 的 bug。如果您有興趣為一個(gè)有價(jià)值的開(kāi)放源碼項(xiàng)目作貢獻(xiàn),那么 eXist 就是一個(gè)值得您去貢獻(xiàn)的項(xiàng)目。但是使得它對(duì)于程序員來(lái)說(shuō)是一個(gè)試探性項(xiàng)目的不完全性也使得它不適合于生產(chǎn)系統(tǒng)。
![]() ![]() |
![]()
|
- 您可以參閱本文在 developerWorks 全球站點(diǎn)上的 英文原文。
- 從 SourceForge 下載 eXist。
- eXist 運(yùn)行在 XML Apache Project 的 Cocoon 應(yīng)用服務(wù)器上,并綁定了 Jetty servlet 引擎。但是它也可以集成到其他 servlet 容器中,比如 Apache Jakarta Project 的 Tomcat。
- eXist 安裝程序是用 Julien Ponge 的開(kāi)放源碼的 IzPack 構(gòu)建的。
-
在線(xiàn)
閱讀 Elliotte Rusty Harold 的書(shū)籍 Processing XML with Java(Addison Wesley Professional,2002 年),或者購(gòu)買(mǎi) 紙版圖書(shū)。
- 探索 Java Network Programming(O′Reilly Media,2004 年),該書(shū)解釋了
URL
和URLConnection
類(lèi)與諸如 eXist 的 REST 接口這樣的 HTTP 服務(wù)器通信。 - 閱讀 Ronald Bourret 的 solid introduction,介紹了如何結(jié)合使用 XML 和各種類(lèi)型的數(shù)據(jù)庫(kù)系統(tǒng)。
- 了解 IBM 和 Oracle 領(lǐng)導(dǎo)專(zhuān)家組開(kāi)發(fā) Java Specification Request 225, XQuery API for Java。當(dāng)前,可得到該規(guī)范的一個(gè)早期草案。
- 打印出來(lái)的話(huà),W3C 的 XQuery 規(guī)范有好幾百頁(yè)。作者推薦您從 XML Query Use Cases 開(kāi)始閱讀。
- 通過(guò)閱讀 W3C Recommendation,更多地了解 XML Path Language (XPath)。
- 閱讀 XUpdate 規(guī)范。
- 作者的服務(wù)器 Eliza 是根據(jù) Neal Stephenson 的 Baroque Cycle 中的 Eliza de la Zeur 命名的。
- 閱讀 developerWorks 上 Elliotte Rusty Harold 的 管理 XML 數(shù)據(jù) 專(zhuān)欄以前的各期文章。
- 在 developerWorks 中國(guó)網(wǎng)站 XML 專(zhuān)區(qū) 找到數(shù)百篇 XML 文章。
- 了解如何才能成為 IBM 認(rèn)證的 XML 及相關(guān)技術(shù)的開(kāi)發(fā)人員。
凡是有該標(biāo)志的文章,都是該blog博主Caoer(草兒)原創(chuàng),凡是索引、收藏
、轉(zhuǎn)載請(qǐng)注明來(lái)處和原文作者。非常感謝。