级别: 初级 Arun Gaikwad (agaikwat@comcast.net), 独立软件顾问
2002 年 9 月 01 日 本文是对一个名为 Xindice(发音为 zeen-dea-chay)的开放源码 Native-XML 数据库系统的简介。它也是对 Native-XML 数据库概念的简介。
简介
随着 XML 本身日益流行(Web 服务就是 XML 的最新应用),Native-XML 数据库系统(NXD)的重要性也在不断增加。在提到“XML 数据库”这一词时,会引发许多疑问,包括:
- 为什么要使用另一种类型的数据库技术呢?
- 它与关系数据库管理系统(RDBMS)有什么不同呢?
- 什么时候我应当使用 Native-XML 数据库系统,而什么时候应当使用关系数据库系统呢?
- 有哪些 Native-XML 数据库产品可供使用呢?
我将在名为 Xindice 的 Native-XML 数据库系统的帮助下设法回答其中的一些问题。
Xindice 是一个开放源码 Native-XML 数据库系统。在本文中,您将学习如何:
- 安装 Xindice
- 创建和删除集合
- 将文档插入这些集合以及删除这些集合中的文档
- 使用 XQuery 查询这些文档
可以在命令行上执行这些操作,或者使用 Java API 将它们嵌入到 Java 程序中。您还将学习使用 Java API 来编写 JDBC 样式的程序,以便与 Xindice 进行通信。
为什么需要 Native-XML 数据库系统?
您可能认为 XML 数据库系统是多余的,但一旦开始使用它,您会惊奇地发现如果没有它您都不知道该怎么活了。我这样说纯粹是出于个人体验。大约两年前当我第一次听说 Native-XML 数据库系统时,我完全没当一回事,并且认为它只是一种宣传而已。那个时候,我正参与为一家大型的金融经纪公司进行项目开发。我们打算使用 XML 来发送和接收金融传输数据。有必要将传输数据保存在某种永久性存储器中。作为一名关系数据库程序员,我的首选是使用关系数据库系统保存这些 XML 文档。我决定使用新型 RDBMS 支持的 CLOB(字符大对象,Character Large Object)来保存这些 XML 文档。因为 RDBMS 支持 Java API 插入和检索 CLOB,所以这是一项非常轻松的任务。随着我们项目的进展,我发现这种方法有一个重要缺陷。它只能进行 DIDO(进文档,出文档)。不能从 DOM 树检索部分文档或节点。我本来想找到一种非常有用的工具,它可以保存 XML 文档、在节点上执行类似数据库的查询以及检索部分或整个文档。这时 NXD 引起了我的注意。如果我必须重新做这个项目,我肯定使用 NXD。如果您需要简单的 DIDO 功能,您可能希望使用 RDBMS 保存您的文档,但是为了扩展功能(如 Query 和 Update),您应当考虑 NXD。
有时候,人们通过将文档节点映射成关系格式来设法把 XML 文档保存到规范化的关系数据库表中。这种做法并非始终都是轻而易举的。从 RDBMS 表构建 XML 文档相对容易,但不易存储它们,因为 XML 文档是层次结构的,并且几乎都是自由格式的。一些可能适合 NXD 的应用包括:
- 会员数据库
- 目录
- 公司门户
- 部件数据库
- 企业对企业文档交换
- Web 服务
目前许多可用的数据库产品都宣称是 Native-XML 数据库系统。当我对其中的一些产品进行评估时,发现有两个产品名列前茅。一个是商业产品,另一个是 Apache 的 Xindice。那个商业产品的功能非常强大,并提供了 GUI 界面来执行管理工作,而 Xindice 是仍然在不断改进的开放源码项目。Xindice 提供了命令行界面来管理数据库和 Java API。由于 Xindice 的简易性、开放源码特性和强大的集合管理,所以我选择它来编写这篇文章。由 Chaudhri、Rashid 和 Zicari 编辑的即将出版的书籍
XML Data Management讲述了许多其它产品、案例研究和性能基准测试(请参阅
参考资料)。
现在,让我们看看如何设置和使用 Xindice。
Xindice 安装
安装和配置非常容易。我花了 15 分钟就安装并配置好了 Xindice。下面是所需的步骤:
- 从
www.xindice.org下载 zip 文件。
- 将文件解压缩到合适的目录。
- 将 Xindice bin 目录添加到路径中。例如,
C:\Xindice\xml-xindice-1.0\bin 。
- 设置 JAVA_HOME 环境变量,使之指向安装 JDK 的位置。请记住,您需要 Sun 的 Java SDK 版本 1.3 或更高版本。
- 设置 XINDICE_HOME 环境变量,使之指向安装 Xindice 的位置。
- 将 Xindice.jar 文件添加到 CLASSPATH。例如,
C:\Xindice\xml-xindice-1.0\java\lib\Xindice.jar 。
- 启动数据库服务器。例如,转到目录
C:\Xindice\xml-xindice-1.0
- 输入
startup 启动运行在端口 4080 上的服务器
- 从您的 Web 浏览器定位到
http://localhost:4080 ,并查看 Xindice Web 页面
Xindice 管理
现在,您将执行一些基本的管理工作,如创建集合。集合类似于 RDBMS 中的表。集合可以是基于模式的,也可以是基于非模式的。基于模式的集合需要以良好定义的 XML Schema 作为开始。Xindice 集合无需 XML Schema。让我们创建一个名为
partsdb的集合。
在命令行上,输入:
xindiceadmin ac -c /db -n partsdb
|
响应是:
如果您尝试再次执行该命令,响应是:
ERROR: Collection Duplicated.
|
您已经成功创建了集合。现在,通过输入下述命令列出集合:
响应是:
要删除集合,可以使用参数
dc(不是
lc)。
集合管理
在本节,我将为您演示如何管理集合。要将名为 parts.xml(请参阅
清单 1)的新文档添加到集合中,使用命令:
xindice ad -c /db/partsdb -f C:\xml\parts.xml --n parts
|
parts 是键。如果省略了该键(它是
--n 选项),Xindice 会创建自己的键。
清单 1. parts.xml
<?xml version="1.0"?>
<parts>
<part sku="101">
<desc>Ball Bearing</desc>
<maker>S.K.F.</maker>
<instock>Yes</instock>
<price>$20.00</price>
</part>
<part sku="102">
<desc>Gasket</desc>
<maker>A.B.C.</maker>
<instock>Yes</instock>
<price>$2.00</price>
</part>
</parts>
|
当您添加文档时,应当验证其 XML 语法是否正确。现在,通过发出下列命令,您可以检索这个文档:
xindice rd -c /db/partsdb -n parts -f
<your file>
|
文档用您提供的文件名进行保存。如果省略了文件名,则显示文档。类似地,可以通过使用
dd命令选项删除该文档。
查询文档
您可以对文档执行一些查询。Xindice 使用类 XQuery 的语法。如果您想检索 SKU 为 101 的部件的有关信息,请输入:
xindice xpath -c /db/partsdb -q /parts/part[@sku="101"]
|
清单 2显示了文档中的查询结果。
清单 2. 查询结果
<?xml version="1.0"?>
<part sku="101" xmlns:src="http://xml.apache.org/xindice/Query"
src:col="/db/partsdb" src:key="parts">
<desc>Ball Bearing</desc>
<maker>S.K.F.</maker>
<instock>Yes</instock>
<price>$20.00</price>
</part>
|
请注意,Xindice 在 part 标记中添加了一些新的属性。这些属性非常有用,可以用来发现文档的出处,例如集合(
src:col )和键(
src:key )。
命令行操作当然是有用的,但是,任何工具的实际能力在于利用 API 进行编程。Xindice 提供了 Java API 来开发应用程序。我将简要研究如何编写 Java 程序来访问 Xindice。
使用 Java 进行应用程序开发
清单 3显示了一个 Parts.java 程序,该程序访问存储在 partsdb 下的 parts 文档:
清单 3. Parts.java 程序
import org.xmldb.api.base.*;
import org.xmldb.api.modules.*;
import org.xmldb.api.*;
public class Parts {
public static void main(String[] args) throws Exception {
Collection col = null;
try {
String driver = "org.apache.xindice.client.xmldb.DatabaseImpl";
Class c = Class.forName(driver);
Database database = (Database) c.newInstance();
DatabaseManager.registerDatabase(database);
col = DatabaseManager.getCollection("xmldb:xindice:///db/partsdb");
String xpath = "//parts/part[@sku='101']";
XPathQueryService service =
(XPathQueryService) col.getService("XPathQueryService", "1.0");
ResourceSet resultSet = service.query(xpath);
ResourceIterator results = resultSet.getIterator();
while (results.hasMoreResources()) {
Resource res = results.nextResource();
System.out.println((String) res.getContent());
}
}
catch (XMLDBException e) {
System.err.println("XML:DB Exception occurred " + e.errorCode);
}
finally {
if (col != null) {
col.close();
}
}
}
}
|
在您编译并执行了 Parts.java 程序之后,它输出类似于
清单 2的 XML 文档。Java 代码是自说明的,但是让我们研究一些细节。请注意,这个程序假定 Xindice 服务器与该程序运行在相同的机器上,但这不是必需的。可以远程访问服务器。如果服务器运行在另一台机器上,例如
myhost,则 URI 为:
Xindice://myhost:4080/db/partsdb
|
现在,研究一下代码的详细信息。开始的三行是所需的 Java 类的导入(import)语句。
import org.xmldb.api.base.*; // imports base API module.
// Required by all applications using XML:DB.
import org.xmldb.api.* // imports DatabaseManager Class.
import org.xmldb.api.modules.*; // XpathQueryService is a module defined in the API.
|
下一步就是按照下列代码所做的那样注册数据库驱动程序:
String driver = "org.apache.xindice.client.xmldb.DatabaseImpl";
Class c = Class.forName(driver);
Database database = (Database) c.newInstance();
DatabaseManager.registerDatabase(database);
|
一旦注册了驱动程序,通过调用 getCollection 方法并提供如下所示的数据库 URI,您就可以访问并检索集合:
col = DatabaseManager.getCollection("xmldb:xindice:///db/partsdb");
|
接下来,获取对名为 XPathQueryService 服务的引用,如下所示:
String xpath = "//parts/part[@sku='101']";
XPathQueryService service =
(XPathQueryService) col.getService("XPathQueryService", "1.0");
ResourceIterator results = resultSet.getIterator();
|
下面的步骤相当简单 ― 只要遍历结果集并将其打印出来:
while (results.hasMoreResources()) {
Resource res = results.nextResource();
System.out.println((String) res.getContent());
}
|
使用 XUpdate 进行数据库更新
到目前为止,您已经了解了如何在 Xindice 中存储和检索 XML 文档。但是如何更新这些已存储的文档呢?答案是使用 XUpdate。可以使用 XUpdate 添加和删除元素,以及更改元素的内容。更新 Xindice 的最好方法就是将 XUpdate 语句嵌入到 Java 程序中。在本节,您将看到 XUpdate 的一些重要特性以及将 XUpdate 嵌入 Java 程序的示例。
注:XUpdate 规范仍在开发之中。
使用 XUpdate 可以执行下列(和其它)重要操作。
-
xupdate:insert-before
在选定的节点前插入新节点。
在 partsdb XML 文档中的
maker元素前插入名为
model的新元素,如下所示:
<xupdate:modifications version="1.0" xmlns:xupdate=http://www.xmldb.org/xupdate>
<xupdate:insert-before select="/parts/part[@sku="101"]/maker">
<xupdate:element name="model">BAB-101</xupdate:element>
</xupdate:insert-before>
</xupdate:modifications>
|
这更新了 partsdb XML 文档。
清单 4显示了新文档。
清单 4. 新文档
<?xml version="1.0"?>
<parts>
<part sku="101">
<desc>Ball Bearing</desc>
<model>BAB-101</model>
<maker>S.K.F.</maker>
<instock>Yes</instock>
<price>$20.00</price>
</part>
<part sku="102">
<desc>Gasket</desc>
<maker>A.B.C.</maker>
<instock>Yes</instock>
<price>$2.00</price>
</part>
</parts>
|
-
xupdate:insert-after在选定的节点后插入了一个新元素。
insert-after 类似于
insert-before ,但是在选定的节点之后添加元素。可以如下所示插入元素
model:
<xupdate:modifications version="1.0" xmlns:xupdate=http://www.xmldb.org/xupdate>
<xupdate:insert-after select="/parts/part[@sku="101"]/desc">
<xupdate:element name="model">BAB-101</xupdate:element>
</xupdate:insert-after>
</xupdate:modifications>
|
-
xupdate:update替换所有选定节点的子节点。
使用
xupdate:update 将 SKU 为 102 的部件的价格更改为 $31.00,如下所示:
<xupdate:modifications version="1.0" xmlns:xupdate=http://www.xmldb.org/xupdate>
<xupdate:update select="/parts/part[@sku="102"]/price">31.00</xupdate:update>
</xupdate:modifications>
|
-
xupdate:append将特定的节点附加到选定的节点。
附加与插入非常相似。
-
xupdate:remove除去选定的节点。
可以删除名为
model元素,如下所示:
<xupdate:modifications version="1.0" xmlns:xupdate=http://www.xmldb.org/xupdate>
<xupdate:remove select="/parts/part[@sku="101"]/model"/>
</xupdate:modifications>
|
-
xupdate:rename重命名选定的节点。
可以将元素
maker重命名为
manufacturer,如下所示:
<xupdate:modifications version="1.0" xmlns:xupdate=http://www.xmldb.org/xupdate>
<xupdate:rename select="/parts/part/maker">manufacturer</xupdate:rename>
</xupdate:modifications>
|
-
xupdate:variable定义变量。
使用
xupdate:variable 定义变量并将选定的节点赋给它。例如,假定您希望移动
price之后的
instock 节点。可以使用
xupdate:variable 、
xupdate:remove 和
xupdate:insert-after 完成该工作,如下所示:
<xupdate:modifications version="1.0" xmlns:xupdate=http://www.xmldb.org/xupdate>
<xupdate:variable name=v_instock select="/parts/part/instock"/>
<xupdate:remove select="/parts/part/instock"/>
<xupdate:insert-after select="/parts/part/price">
<xupdate:value-of select="$v_instock"/>
</xupdate:insert-after>
</xupdate:modifications>
|
可以看到,XUpdate 是用来更新 XML 内容的一种非常简单的语言。还可以使用 Java API 来实现这些修改。
清单 5显示了一个简单的 Java 程序,它可以执行先前描述的
xupdate:insert-before操作。该程序类似于
清单 3中从数据库打印 XML 内容的 Parts.java 程序。
清单 5. 执行 xupdate:insert-before 的 Java 程序
import org.xmldb.api.base.*;
import org.xmldb.api.modules.*;
import org.xmldb.api.*;
public class PartsXupdate {
public static void main(String[] args) throws Exception {
Collection col = null;
try {
String driver = "org.apache.xindice.client.xmldb.DatabaseImpl";
Class c = Class.forName(driver);
Database database = (Database) c.newInstance();
DatabaseManager.registerDatabase(database);
col = DatabaseManager.getCollection("xmldb:xindice:///db/partsdb");
String xupd = "<xupdate:modifications version="1.0"" +
"xmlns:xupdate=http://www.xmldb.org/xupdate>" +
"<xupdate:insert-before select="/parts/part[@sku="101"]/maker">" +
"<xupdate:element name="model">BAB-101</xupdate:element>" +
"</xupdate:insert-before>" +
"</xupdate:modifications>";
/* We are using XUpdateQueryService */
XUpdateQueryService service =
(XUpdateQueryService) col.getService("XUpdateQueryService", "1.0");
service.update(xupd);
}
catch (XMLDBException e) {
System.err.println("XML:DB Exception occurred " + e.errorCode);
}
finally {
if (col != null) { col.close();}
}
}
}
|
请注意,我使用了 XUpdateQueryService 而不是 XPathQueryService。
结束语
在这篇文章中,您已经了解了如何使用 Native-XML 数据库系统构建基于 XML 的应用程序。NXD 不会代替 RDBMS。大多数情况下,NXD 和 RDBMS 可以一起使用。NXD 将来肯定会扮演非常重要的角色。
参考资料
- 您可以参阅本文在 developerWorks 全球站点上的
英文原文.
- 请下载
Xindice。
- 在 Ron Bourret 的网站上查找有关
XML 和数据库的信息。
- 请阅读 Cameron Laird 的系列文章“Adventures in high-performance XML persistence”的
第 1 部分和
第 2 部分,这个系列的文章很好地讨论了存储 XML的其它方法(
developerWorks,2002 年 7 月和 2002 年 9 月)。
- 请查阅由 Akmal B. Chaudhri、Awais Rashid 和 Roberto Zicari 合著的
XML Data Management
(Addison-Wesley,ISBN 0201844524)。该书提供了大量有关 XML 数据库产品体系结构、案例研究和性能基准测试的有用信息。
- 如果您有兴趣将 XML 存储在关系数据库系统中,请查看 Mark Graves 所著的
Designing XML Databases(Prentice-Hall,ISBN 0130889016)。这本书非常有用,它描述了几种方法,并提供了许多新型 RDBMS 的 Java 代码示例。
- 请研究 Richard Edwards 博士有关
XML 资源库和
minx的成果,这是用来将 XML 文档存储在关系数据库中的通用体系结构。
- 在 Akmal B. Chaudhri 的
基准测试页面上可以发现许多 XML 数据库系统的性能基准测试,它们是由世界各地的不同研究小组开发的。
关于作者
对本文的评价
|