IBM®
跳转到主要内容
    中国 [选择]    使用条款
 
 
Select a scope: Search for:    
    首页    产品    服务与解决方案     支持与下载    个性化服务    
跳转到主要内容

developerWorks 中国  >  Web development | XML  >

Xindice 简介

开放源码 Native-XML 数据库系统

developerWorks
文档选项

未显示需要 JavaScript 的文档选项


级别: 初级

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。下面是所需的步骤:

  1. www.xindice.org下载 zip 文件。
  2. 将文件解压缩到合适的目录。
  3. 将 Xindice bin 目录添加到路径中。例如, C:\Xindice\xml-xindice-1.0\bin
  4. 设置 JAVA_HOME 环境变量,使之指向安装 JDK 的位置。请记住,您需要 Sun 的 Java SDK 版本 1.3 或更高版本。
  5. 设置 XINDICE_HOME 环境变量,使之指向安装 Xindice 的位置。
  6. 将 Xindice.jar 文件添加到 CLASSPATH。例如, C:\Xindice\xml-xindice-1.0\java\lib\Xindice.jar
  7. 启动数据库服务器。例如,转到目录 C:\Xindice\xml-xindice-1.0
  8. 输入 startup 启动运行在端口 4080 上的服务器
  9. 从您的 Web 浏览器定位到 http://localhost:4080 ,并查看 Xindice Web 页面




回页首


Xindice 管理

现在,您将执行一些基本的管理工作,如创建集合。集合类似于 RDBMS 中的表。集合可以是基于模式的,也可以是基于非模式的。基于模式的集合需要以良好定义的 XML Schema 作为开始。Xindice 集合无需 XML Schema。让我们创建一个名为 partsdb的集合。

在命令行上,输入:

xindiceadmin ac -c /db -n partsdb

响应是:

Created db/partsdb

如果您尝试再次执行该命令,响应是:

ERROR: Collection Duplicated.

您已经成功创建了集合。现在,通过输入下述命令列出集合:

xindiceadmin lc -c /db

响应是:

System
Partsdb

要删除集合,可以使用参数 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:variablexupdate:removexupdate: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 数据库系统的性能基准测试,它们是由世界各地的不同研究小组开发的。


关于作者

Arun Gaikwad 是一位独立软件顾问。在大型软件项目的设计、开发和实现方面,他有超过 11 年的工作经验。可以通过 agaikwat@comcast.net与他联系。




对本文的评价










回页首


IBM 公司保留在 developerWorks 网站上发表的内容的著作权。未经IBM公司或原始作者的书面明确许可,请勿转载。如果您希望转载,请通过 提交转载请求表单 联系我们的编辑团队。
    关于 IBM 隐私条约 联系 IBM 使用条款