XML与数据库目录1.0 简介 1.0 简介 (Introduction)本文对怎样使用XML和数据库做了总体回顾,描述了以数据为中心和以文档文中心的文档的差异如何影响到在数据库中的应用,XML和关系型数据库的一般用法,以及什么是原生XML数据库和何时使用它。 2.0 XML是数据库吗?(Is XML a Database?)在开始讨论XML和数据库之前,我们先回答许多人提过的问题:“XML是数据库吗?” 如果仅按数据库这个术语的本质来看,XML文件是数据库。即它是数据的集合。在许多方面看起来它和其他文件没什么区别 -- 无论如何,每个文件都含有某种类型的数据。作为一种“数据库”格式,XML有一些优势:例如,它是自描述的(所用的标记描述了数据的结构和类型,尽管缺乏语义),可交换的(portable)(Unicode),能够以树型或图形结构描述数据。同样它也有缺点,例如,它是冗余的,由于要对它进行解析和文本转换,所以数据访问速度较慢。 一个更有用的问题就是在宽松的意义上,XML及其周边技术是否可以算作“数据库” -- 即数据库管理系统(DBMS)。答案是“在某种程度上是(sort of)”。从正面来说,XML提供了许多数据库所具备的东西:存储(XML文档), 模式(DTD, XML schema语言), 查询语言(XQuery, XPath, XQL, XML-QL, QUILT等等),编程接口(SAX, DOM, JDOM)等等。从反面来说,它缺少一些真正的数据库所应具备的东西:高效的存储,索引,安全,事务和数据一致性,多用户访问,触发器,在多个文件中查询等等。 XML适合于用作所谓“数据库”的一个好例子就是 .ini文件 -- 它包含应用程序的配置信息。与其写一个处理以逗号分隔(comma-delimited)的文件的解析器,开发一种小型的XML语言并写一个解释它的SAX程序要容易的多。此外,XML允许使用嵌套的实体,而逗号分隔的文件(comma-delimited files)很难做到这点。然而,说它就是数据库还很勉强,因为它是线性读写的,而且仅用在程序开始和结束时。 比较适合于XML数据库的一些复杂的数据集就是个人通讯录(名字,电话号码,地址等),或用于描述浏览器书签以及用Napster偷来的MP3。然而,由于dBase和Access之类的数据库物美价廉,即使在这种情况下似乎也没有多少理由把XML文件作为数据库使用。XML的唯一真正好处就是数据的可交换性(portable),由于有越来越多的工具可以用来将数据库当作XML进行存取,这一点好处似乎也要打些折扣。 3.0 为什么要用数据库?(Why Use a Database?)当你开始考虑XML和数据库的时候首先要回答这个问题:为什么你会先想到使用数据库?你是否想利用现有数据?是否想找个地方存储Web页面? 是否在电子商务中使用数据库,而XML在其中作为数据传输载体? 对这些问题的回答将会极大地影响你对数据库和中间件(如果有的话)的选择, 以及如何使用数据库。 例如,你有个电子商务的应用,将XML用作数据交换。那么你的数据最好有个高度规整的结构并且供非XML程序使用。还有,XML文档所用的某些东西如实体和编码对你来说可能并不重要 -- 总之,你感兴趣的是数据,而不是它在XML内如何存储。在这种情况下,你大概需要一个关系型数据库以及在XML和数据库之间转换数据的软件。如果你的应用程序是面向对象的,你甚至还需要一个在数据库或XML中存取这些对象的系统。 另一方面,假如你要从一些面向散文(prose-oriented)的XML文档建立一个网站。你不但要管理这个网站,还要提供一个途径让用户可以查找内容。你的文档看起来结构比较松散,其中的实体的使用对你来说可能更重要,因为它们是文档结构的重要部分。这种情况下,你也许需要一个原生XML数据库(native XML database)或内容管理系统(content management system)。这就使你可以保持文档的物理结构,支持文件级的事务处理,以及使用XML Query语言进行查询。 4.0 数据和文档 (Data versus Documents)在选择数据库时最重要因素大概就是你想在数据库存储数据还是文档。例如,是简单地把XML当作数据库和(可能不支持XML)应用程序之间的数据转换工具,还是用于集成,就像XHTML和DocBook中的那样?通常这是个偏好,但是却非常重要,因为所有以数据为中心的(data-centric)文档有着许多相同的特性,所有以文档为中心的(document-centric)也有许多相同的特性。这会影响到XML在数据库中如何存储。下面两部分中我们就来考察这些特性。 (历史背景:我在xml-dev邮件列表上第一次听说data-centric和document-centric这些术语,不知道是谁发明的,但是我在1997的消息中发现有使用document-centric的,从1998年以后这两个术语都有使用。) 4.1 以数据为中心的文档 (Data-Centric Documents)以数据为中心的文档就是将XML用作数据的传输载体,专门提供给机器消费,其实没有必要全部采用XML。也就是说,对于应用程序或数据库而言,(在某个时间段内)数据是否以XML文档的形式存储并不重要。以数据为中心的文档的例子有销售订单、航班时刻表、科研数据及股市汇率。 以数据为中心的文档的特点是结构相当规整,数据粒度精细(fine-grained data)(即最小的独立数据单位只存在于PCDATA元素或属性级别),很少或没有混合内容。除非在对文档进行验证的时候,同级元素或PCDATA的出现次序一般来说并不重要。 以数据为中心的文档中的这类数据可以来自数据库(此时要输入给XML)或在数据库之外(此时要将其存入数据库)。前者的一个例子就是关系数据库现存的大量数据;而从测量系统采集并转化为XML的科研数据就是后者的例子。 例如,下面的销售订单就是以数据为中心的: 除了像销售订单这种显而易见的以数据为中心的文档之外,许多以文本为主的(prose-rich)文档也可以是以数据为中心的。例如,Amazon.com用来显示书籍信息的一个页面。尽管页面上大部分内容都是文本,这些文本的结构是非常规则的,许多都和其它书籍的描述相同,每个页面特有的文本并不很多。这样,就可以从数据库中取出书籍的相关资料,转换为简单的、以数据为中心的XML文档,再用XSL样式表生成页面。一般来说,那些用数据库中的数据填充模板,动态生成HTML文件的网站都可以转而使用一系列以数据为中心的XML文档和XSL样式表。 例如,下面是个描述航班信息的文档: 从下面的XML文件和一个简单的样式表中创建这个文档:4.2 以文档为中心的文档 (Document-Centric Documents)以文档为中心的文档通常是供人消费的。例如书籍、email、广告以及几乎所有人工写成的XHTML文件。其特性为结构不太或根本不规则、数据粒度大(larger grained data)(最小的独立数据单位可能存在于包含混合内容的元素甚至整个文档本身),混合内容多。同级元素或PCDATA出现的次序一般来说总是非常重要的。 以文档为中心的文档通常是以XML手工写成,或从其他格式(如RTF, PDF, SGML)转换到XML,与以数据为中心的文档不同,它们通常不来源于数据库。(由插入到模板中的数据得到的文档是以数据为中心的;更多信息请看4.1节末尾部分)。将各种格式转换为XML的软件信息,请参阅XML软件相关链接。 例如,下面这个产品说明是以文档为中心的: 4.3 数据、文档和数据库(Data, Documents, and Databases)实际上,以数据为中心和以文档为中心的文档之间的差别不一定很明显。例如,另一种以数据为中心的文档比如发票,可能含有大粒度的、非结构化的数据比如零件说明;另一种以文档文中心的文件如用户手册,可能包含细粒度的结构规则的数据(通常为元数据)比如作者和修订日期。其它例子包括法律和医学文书,虽然以散文的形式写成但是却包含离散的数据块例如日期、名称和操作程序,出于法定原因通常要以完整的文件形式存储。 除此之外,弄清文件的这两种特点有助于选择数据库的类型。一般来说,将数据存储于传统的数据库,例如关系型,面向对象型或层次型数据库。这可由第三方的中间件完成或由数据库本身提供内在支持。对于后者,该数据库被称作支持XML的(XML-enabled)。文档可被存储在原生(native)XML数据库(专为存储XML而设计的数据库)或内容管理系统(建在原生XML数据库之上专门用来管理文档的程序)。 这些原则并不是绝对的。如果对XML特有的功能不很看重,数据,特别是半结构化的数据可以存储在原生XML数据库,文档也可以存储到传统数据库。何况传统数据库与原生XML数据库之间的界限越来越模糊,传统数据库增加了原生XML的能力,而原生XML数据库增加了对文档存储在外部(通常为关系型)数据库的支持。 本文剩下的部分就有关数据(第5节)和文档(第6节)的存储和读取的策略与问题展开讨论。关于最新的XML数据库产品,请见 XML Database Products。 5.0 数据的存取(Storing and Retrieving Data)为了在XML文件和数据库之间交换数据,有必要将XML文件的schema(DTD,XML Schema, RELAX NG等)映射到数据库的schema。用于数据转换的软件就建在这种映射之上。该软件可以使用XML Query语言(如XPath,XQuery,或其他专用语言)或简单地按照映射(SELECT * FROM Table的XML对等式)转换数据。对于后者,文档的结构必须完全符合映射所要求的结构。由于通常不易做到这点,使用这种策略的产品一般要和XSLT一起使用。在数据转换到数据库之前,先将文件按照映射所要求的结构进行转换,然后转存数据。相应地,数据从数据库中取出以后,结果文件要被转换成应用程序所需的结构。 5.1 映射[XML]文件Schema到数据库Schema (Mapping Document Schemas to Database Schemas)文件schema到数据库schema的映射是在元素类型、属性和文本上进行的。这时几乎总是忽略物理结构(例如实体、CDATA部分及编码信息)及某些逻辑结构(如处理指令、注释以及元素和PCDATA在父元素内出现的顺序)。这样比完全照搬更为合理,因为数据库和应用程序只需关心XML文件中的数据。例如,在上述的销售订单中,客户代号是在CDATA部分,还是外部实体中,或直接就是PCDATA并不重要,同样,客户代号出现在订货日期之前或之后也无关紧要。 这种方法的一个后果是能否保证文件有“往返车票” -- 将文件中的数据存入数据库后,又从数据库中的数据建立文件,而这个文件往往和原来的文件不同(哪怕从最一般的意义上讲)。在选择软件是要考虑到是不是允许这种情形发生。 将一个XML文件的schema映射到数据库的schema有两种方法:基于表格的映射和对象-关系映射。 5.1.1 基于表格的映射 (Table-Based Mapping)许多转换XML到数据库的中间软件都采用基于表格的映射。它把XML文件看作一个(或一组)表格,也就是说,XML文件的结构必须是下面这种样子,如果只是单一表格的话,就不再需要<database>元素和其他<table>元素:根据所用软件的不同,可以指定将各字段数据以子元素或属性存储,也可以指定这些元素或属性的名字。此外,采用基于表格映射方式的软件还可能允许在文件开始的地方包含表格或各字段的元数据,或者将其作为各表格或元素的属性。注意这里所说的“表格”是泛指的表格。当将数据从数据库中转到XML文件时,“表格”可以是任何结果集,反之,“表格”可以是普通的表格或可更新的视图。 基于表格的映射对存取关系型数据比较适用,比如在两个关系型数据库之间转换数据。其明显不足就是不适于与上述格式不符的XML文件。 5.1.2 )对象-关系映射 (Object-Relational Mapping) 许多转换XML到数据库的中间软件都采用基于表格的映射。它把XML文件看作一个(或一组)表格,也就是说,XML文件的结构必须是下面这种样子,如果只是单一表格的话,就不再需要<database>元素和其他<table>元素:根据所用软件的不同,可以指定将各字段数据以子元素或属性存储,也可以指定这些元素或属性的名字。此外,采用基于表格映射方式的软件还可能允许在文件开始的地方包含表格或各字段的元数据,或者将其作为各表格或元素的属性。注意这里所说的“表格”是泛指的表格。当将数据从数据库中转到XML文件时,“表格”可以是任何结果集,反之,“表格”可以是普通的表格或可更新的视图。 基于表格的映射对存取关系型数据比较适用,比如在两个关系型数据库之间转换数据。其明显不足就是不适于与上述格式不符的XML文件。 5.1.2 对象-关系映射 (Object-Relational Mapping)所有支持XML的关系型数据库和某些中间件都可以使用对象-关系的映射方式。它将XML文件中的数据视为特定的对象树的模型。在这个模型中,元素及其类型、元素内容或混合内容(复合元素类型)通常被视为类。只具有PCDATA内容的元素(简单元素类型)、属性以及PCDATA都被当作简单属性。然后通过传统的对象-关系映射技术或SQL 3的对象视图将该模型映射到关系型数据库。也就是说,类被映射到表格,简单属性被映射到字段,而值为对象属性被映射为成对的主键/外键(primary key/foreign key)。 (所谓“对象-关系映射”实际上名不副实。因为对象树可以被直接映射到面向对象型和层次型数据库,然而,但是由于大多数使用这种映射方式的主流产品使用的其实是关系型数据库,所以“对象-关系映射”也就广为人知。) 我们在理解这种映射所用的对象模型的时候要知道,这个对象模型不是文件对象模型(DOM)。所有XML文件的DOM都是一样的,而上述描述文件数据的模型对于每个DTD所定义的XML文件都不一样,例如,上述销售订单的模型是一个由四个类所组成的对象树--SalesOrder, Customer, Item, 和Part, 如下图所示: 在由同一个文件产生的DOM中,对象树的组成是元素、属性和文本: 模型中的对象是否被实例化要取决于所用的软件。有些软件允许依据模型产生类,然后可以在程序中使用由这些类所产生的对象。在这些产品中,数据是在XML文件 - 对象 - 数据库之间传递的。其他产品是直接在XML文件和数据库之间进行数据转换的,对象只是作为这种过程的可视化帮助工具。生成这些中间对象是否有用完全取决于你的应用程序。 (根据Sun的 Java Architecture for XML Binding,XML文件与对象的绑定通常被称为XML数据绑定(XML data binding), 有些产品支持XML数据绑定,其中许多还可以在对象和数据库之间进行数据交换,更多的信息,请看 XML数据绑定相关资源 XML Data Binding Resources.) 各种产品支持对象-关系映射的具体实现方法有所不同。例如:
关于对象-关系型映射的详细描述,请看第三部分“将DTD映射到数据库”。 5.2 查询语言(Query Languages)许多产品都是按照它们所建的模型直接进行数据交换。由于XML文件的结构和数据库的结构一般不同,这些产品一般都使用了或包括了XSLT样式表。这就允许用户在数据被交换到数据库之前(或相反)根据模型规定的格式对文件进行转换。由于XSLT处理的代价较高,某些产品只提供有限几种这样的转换。 这个问题的长久解决方案就是设计一种可以返回XML[文件]的查询语言。目前来看(2002年2月),大多数这种语言都是在模板中嵌入SELECT语句。到XQuery最后定稿时这个局面有望得到改变,正如主流的数据库产品提供商已经做的那样。不幸的是,几乎所有的XML查询语言(包括XQuery1.0)都只能读取数据,所以当前最需要的是能够插入、更新、删除数据的手段。(从长远来看,XQuery将会增加这种功能。) 5.2.1 基于模板的查询 (Template-Based Query)大多数从数据库读取XML的查询语言是基于模板的,这些语言并没有预先定义XML文件和数据库之间的映射,相反,是将SELECT语句嵌入到模板中,由数据交换软件对结果进行处理。例如,下面的模板(并不是真正产品中的)使用包含了SELECT语句和$column-name值的<SelectStmt>元素来决定将结果放在何处。 这个模板处理之后的结果可能是: 基于模板的查询语言可以做到非常灵活。尽管各个产品的功能不尽相同,但有一些共同特性:
从关系数据库中将数据转换到XML文件时,几乎一定要用到基于模板的查询语言。虽然有些产品也将基于模板的查询语言用于XML文件到关系数据库的数据转换,这时所用的并不是完整的模板语言。相反,他们使用的是上面所述的基于表格的映射。 5.2.2 基于SQL的查询语言 (SQL-Based Query Languages)基于SQL的查询语言使用的是经过修改的SELECT语句,[查询]结果被转换为XML。通过简单地使用嵌套的SELECT语句,就可直接转换成符合对象-关系映射的嵌套的XML。或者使用SQL 3的对象视图也可直接转换成XML。最后还可使用 OUTER UNION语句和特殊标记来决定怎样将结果转换成XML。 5.2.3 XML Query Languages基于模板和基于SQL的查询语言只能用于关系数据库,与此不同,XML查询语言可用于任何XML文档。为了把它用于关系数据库,必须把数据库中的数据看作XML的模型,这样才能对虚拟的XML文件进行查询。 对于XQuery, 基于表格的映射或对象-关系型映射都可以使用。当使用基于表格的映射时,各个表格被视为单独的文件,像SQL中的一样, 这些表格的结合(joints)则在查询[语句]本身中指明。如果使用的是对象-关系型映射,各个表格的层次被当作单个文件,而[表格的]结合在映射中说明。对于大多数关系数据库而言,似乎基于表格的映射更为常用,这是因为它的实现似乎更简单些,SQL的用户对此也更为熟悉。 如果使用XPath在多个表格中进行查询,就必须使用对象-关系映射,这是因为XPath不支持多个文档。因此,如果使用基于表格的映射,可能每次只能对一个表格进行查询。 5.3 原生XML数据库的数据存储(Storing Data in a Native XML Database)还可以将XML文件中的数据存储在原生XML数据库(native XML database)中。这么做有几个理由。首先,当你的数据是半结构化的数据时。也就是说,它的结构是普通的,但是如果将其映射到关系数据库,结果是要么出现大量空值(null)的字段,要么表格的数量过多,浪费空间或效率低下。虽然半结构化的数据可存储到面向对象的或层次型数据库中,你还可以选择将它以XML文件的形式存储于原生XML数据库。 将数据存储在原生XML数据库中的第二个理由是读出速度。根据XML数据库存储数据的物理方式的不同,数据的读出速度可以做到比关系型数据库[的读取速度]快得多。其原因是,原生XML数据库对整个文件一起进行物理存储,和[表示]文件各个部分的物理(而不是逻辑)指针可采用同一存储策略。这就可以不使用连接(joins)或只使用物理连接读取文件,无论哪种情况都比关系型数据库所用的逻辑联结要快。 以上述销售订单文件为例。在关系型数据库中,它可能被存为四个表格 -- SalesOrders, Items, Customers, 和 Parts -- 读取文件时需要将这些表格结合起来。在原生XML数据库中,整个文件可被存储在磁盘的一个地方,在读取文件或其片断时只需要一次查找和一次读取操作。关系数据库在读取数据时则需要四次查找以及至少四次读取操作。 这样做的一个明显缺点就是,只有数据的读取顺序和写入磁盘的顺序相同时,才可以提高速度。如果你想要的数据视图不同,比如只想要客户及其订单列表,性能可能比关系数据库更差。所以,如果你的应用中是单个数据视图为主, 为了提高性能,才可以考虑将数据存储到原生XML数据库。 将数据存储在原生XML数据库中的第二个理由是你想利用XML的独有特性,如执行XML查询。由于今天以数据为中心的应用几乎没有这样做的,而且关系数据库正在逐步支持XML查询语言,这个理由越来越不充分。 将数据存储在原生XML数据库中的一个问题是,大多数原生数据库只能以XML[的形式]返回数据。(支持元素和属性到应用程序变量绑定的只是少数)。如果你的应用程序需要另一种数据格式(很有可能),使用数据之前必须先解析XML。对本地的应用程序而言显然是个缺点,而这种前期准备在(比如)ODBC中就不存在。对于将XML作为数据载体使用的分布式应用程序而言,这个问题不很严重,因为不管用的是哪种数据库,这种前期工作必须要有。 5.4 数据类型,空值,字符集及其他 (Data Types, Null Values, Character Sets, and All That Stuff)本节将就在传统数据库中存储XML文件数据的相关问题展开讨论。(有关数据类型和二进制数据存储的讨论同样适用于原生XML数据库)总的说来,你无法选择数据交换软件解决这些问题的方式。然而,你应当明白这些问题确实存在,这样会有助于你选择软件。 5.4.1 数据类型 Data Types如果单纯从字面上讲,XML不支持任何数据类型。除了非解析实体,XML文件中的所有数据都是文本,尽管它可能表示日期或整数等其他类型。一般来说,数据交换软件负责把(XML文件中的)文本转换成(数据库中的)其他数据类型,反之亦然。但是,能够被识别为特定数据类型的文本格式数目很有限,比如某个JDBC驱动程序所支持的。日期看起来最容易出问题,因为它的格式可能非常多。而数字在各种语言中的格式也不尽相同,也有可能出问题。 5.4.2 二进制数据 (Binary Data)二进制数据在XML文件中的存储方法一般有两种:非解析实体和Base64编码(一种编码方式,将二进制数据映射到US-ASCII码的一个子集)。对于关系型数据库,这两种方法都可能产生问题,因为数据库中二进制数据的存取规则非常严格,可能导致软件出错。此外,由于XML标准标记中没有哪个能指明某个元素含有以Base64编码的数据,所以软件甚至可能无法识别数据是以Base64编码的。最后,与非解析实体或Base64编码元素相关的标记是大多数(全部?)数据转换软件在往数据库中存储时所忽略的方面之一。因此,如果二进制数据对你来说很重要,就应确认你所用的软件是否支持它的存取。 5.4.3 空数据 (Null Data)在数据库术语中,空数据(null data)意味着没有数据。这和值为0的数字或长度为零的字符串区别非常大。例如,假设你收集到的是气象数据,如果温度计不能工作,则数据库中存储的就是null而不是0,否则情况就完全不同了。 XML也支持这种空数据的概念(通过可选(optional)元素或属性)。如果一个可选元素或属性的值为空,就不会包含在文件内。而在数据库中,值为零长度字符串的属性和空元素并不是null:它们的值为零长度的字符串。 当你将XML文档的结构映射到数据库(或反过来)时,你当特别留意,可选元素类型或[空值]属性会被映射到允许空值的字段(nullable columns),反之亦然。如果不是这样的话,可能会产生插入错误(当转换数据到数据库时)或非法文件错误(从数据库中取出数据时)。 与数据库专业相比,XML社区对null含义的表示法更为自由-- 特别是许多XML用户都认为零长度字符串的属性和空元素是“空(null)”的,所以你应该检查一下你的软件是如何处理这种情况的。有些软件为用户提供了选择,可以定义XML中如何表示"null",以及支持XML Schema中的 xsi:null属性。 5.4.4 字符集 (Character Sets)根据定义,除了某些控制字符,XML文件可包含任何Unicode字符。不过,许多数据库对Unicode的支持很有限或根本就不支持,而且需要特殊的配置才能处理非ASCII字符。如果你的文件包含非ASCII字符,要确保你的数据库及数据转换软件对这些字符是否支持及如何支持的。 5.4.5 处理指令和注释 (Processing Instructions and Comments)处理指令和注释并不是XML文档“数据”的一部分,大多数(全部?)数据转换软件都不能处理它们。问题在于这些东西可能出现在XML文档中的任何地方,所以不容易进行基于表格或对象-关系型映射。(一个明显行不通的方案是为这些处理指令和注释建立一个表格,在其他表格加上指向这个表格的外部键(foreign key),每当处理别的表格时,就检查这些表)。所以大多数数据转换软件会简单地忽略它们。如果处理指令和注释对你相当重要,就要检查所用软件对此能否处理及处理方法。或者可以考虑使用原生XML数据库(native XML database)。5.4.6 对标记的存储 (Storing Markup)正如5.1.2 一节所提到的, 有时候需要在数据库中存储混合内容的元素而无须进一步解析。这时, 标记被存储为标记字符(markup is stored with markup characters)。然而,问题出现在如何存储那些不作为标记使用的标记字符。在XML文档中,这些是以 lt, gt, amp, quot 和 apos 实体存储的。在数据库中也可这么做。例如,下面的description:在数据库中可存为: 这样做的一个问题是一些非XML查询语言,如SQL不会在表中搜寻标记和实体的用法并将其正确翻译。这样,如果你打算用SQL来搜索字符串“<foo/>”,你应当知道实际的搜索字符串是“<foo/>”。 另外,如果实体引用被扩展了,数据转换软件无法区别标记和实体。例如,如果上述例子在数据库中按照下面的形式存储,则软件就无法知道<b> , </b> 和<foo/>到底是标记还是文本。 解决这个问题的长久之计就是支持XML的数据库(XML-aware database),在那里,对真正的标记和看起来很像标记的东西的处理方式是不同的。非XML应用程序处理XML时,总是会出现这种问题。 5.5 从关系[数据库]Schema产生DTD或相反 (Generating DTDs from Relational Schema and Vice Versa)在XML文件与数据库之间进行数据转换时经常遇到的一个问题是如何从数据库schema产生DTD或相反。在解释如何做之前,必须指出这是设计阶段的任务。其原因是大多数以数据为中心的应用以及几乎所有的盘点应用软件(vertical applications)都是在已知的DTD或数据库模型上工作的,因此,不会在运行时产生schema。再者,如下所述,schema的产生过程不十分严格。如果应用程序需要在数据库中随机存放XML文件,则应考虑使用使用原生XML数据库,而不是在运行时产生schema. 从DTD产生关系模型(或相反)的最简单方法就是直接借助于对象-关系映射,它有几个可选特性。对于面向对象的数据库也有相似的途径。(关于每种方法的逐步演示,请看Mapping DTDs to Databases.)。 从DTD产生关系模型:
从关系[数据库]模型产生DTD:
这些过程有一些缺点。许多问题都可手工解决,比如名称冲突及指定字段数据类型和长度。(DTD不包含数据类型信息,所以不可能预知数据库中的数据类型。注意,从XML Schema文件可以知道数据类型和长度。) 更加严重的问题是,XML文件所用的数据“模型”通常和数据库中所用的高效率的模型不同(更为复杂)。请看如下XML片断: 从DTD产生关系模型的一般过程来看,通常会产生两个表:一个是customers,另一个是addresses。然而,大多数情况下把address存放在customer表中更为合理。 <Address>元素就是包装元素(wrapper element)的典型例子。采用包装元素的原因有二:首先,这种结构使得文档更容易理解;其次,它可作为一种数据类型使用。例如,可以将<Address>元素传给一个例程,该例程可以将所有地址转换为Address对象,不管它出现在哪里。 虽然包装元素在XML中很有用,但被映射到数据库中的时候会增加额外的结构,很容易出问题。因此,在产生关系模型之前,一般应将其从DTD中除去。由于DTD一般是不允许改变的,而在映射是又不包含包装元素,所以往往会导致实际文档与数据转换软件所要求的文档不匹配。对此可以在运行时转换文件(比如使用XSLT):数据被转到数据库之前去掉包装元素,转出后在加上它。 尽管有这些不足,上述步骤还是为DTD和关系模型之间的转换提供了一个起点,对于大型系统尤为如此。 6.0 文件的存取 (Storing and Retrieving Documents)XML文件的存储方式有两大类:存储于文件系统或作为BLOB存储于关系数据库以获得有限的XML功能,或者将其存储于原生XML数据库。 6.1 将文件存储于文件系统 (Storing Documents in the File System)如果你的文件比较简单,数量不多,最简便的方法就是存储于文件系统。以后可以使用grep之类的工具进行查询或sed来修改。(对XML文件进行全文检索显然不够精确,比如很难区分文本和标记,而且无法理解实体的用法。然而,对于小型系统,这还是可以接受的)如果你想实现简单的事务管理(transaction control),可以将文件放在诸如CVS或RCS等版本管理系统中。 6.2 将文件存储于BLOB (Storing Documents in BLOBs)另一种较为复杂的方法就是将文件存储于关系数据库中的BLOB。这就利用了数据库的一些优点:事务管理、安全、多用户访问等。此外许多关系数据库提供的检索工具可以进行全文检索、近似检索、同义词检索和模糊检索。其中某些工具将会支持XML,这样就可消除将XML文件作为纯文本检索所带来的问题。 如果以BLOB的形式存储XML文件,即使数据库不支持对XML的检索,你也很容易实现自己的XML检索。方法之一是创建两个表:索引表(DB2中的side table)和文件表。文件表包含一个主键和一个存储文件的BLOB字段,索引表内有一个已建立索引值字段以及一个外来键指向文件表中的主键。 文件被存在数据库中之后,就可以搜索所有已建索引的元素和属性实例。每个实例及文件的主键都存于索引表中。这样已建立索引的字段使应用程序可以快速检索某个元素或属性值并获取相应的文件。 举例来说,假如你有一些符合下列DTD的文件,希望建立作者的索引: 你可以用下表来存储它: 假如你在数据库中插入了一个 更复杂的索引表可包含四个字段:元素类型或属性名、(元素或属性)类型、值和文件ID。这样就可在一个表中存放多个标记[文件], 并按名字、类型和值建立索引。写个操作这个表的SAX程序应该不是件难事。 6.3 原生XML数据库 (Native XML Databases)上述的简单系统所提供的功能如果不能满足你的需要,你可以考虑使用原生XML数据库(native XML database)。原生XML数据库是专用于存储XML文件的数据库。和其他数据库一样,它支持事务管理、安全、多用户访问、编程API和查询语言等。与其它数据库的唯一区别就是其内部模型是基于XML的,而不是其他的模型--如关系模型。 显然原生XML数据库最适于存储以文档为中心的文件。这是由于原生XML数据库保留了文件[元素?]顺序、处理指令、注释、CDATA块以及实体引用等,而支持XML的数据库(XML-enabled database)无法做到。此外,原生数据库支持XML查询语言,你可以对它提这样的问题:“找出所有第三段内包含粗体字的文件”,用SQL显然很难进行这样的查询。 原生XML数据库还适用于存储那些“天然格式”为XML的文件,而不管这些文件包含什么内容。例如,电子商务系统消息所用的XML文件。尽管这些文件可能是以数据为中心的,而作为消息来说它们的天然格式是XML。这样当它们被存入消息队列后,建立在原生XML数据库上的消息队列使用起来更为方便。原生XML数据库保留了XML的特性比如XML查询语言,通常能更快地取出整条消息。Web cache是这类应用的另一个例子。 原生XML数据库的其他用途是存储半结构化数据、在某种特定情形下提高存取速度以及存储没有DTD的文件(良构的文件)。前两种已经在5.3 原生XML数据库的数据存储中叙述过。而后一种用非XML的数据库是做不好的。也就是说,原生XML数据库无须事先配置即可接受和存储任何XML文件。将XML文件中的数据转换到关系型或面向对象型数据库必须首先建立映射和数据库模型。无须事先配置对于搜索引擎之类的应用程序来说是有利的,因为没有任何DTD能适用于所有搜索文档。 6.3.1 什么是原生数据库(Native XML Database)?"native XML database"这个术语首先在Software AG 为 Tamino 所做的营销宣传中露面。也许由于它的成功,后来这个术语在同类产品的开发商那里成了通用叫法。它是一个营销术语,从来没有正式的技术定义,这是它的一个缺陷。有一个接近的定义(出自XML:DB mailing list的一个成员)这样定义原生XML数据库(native XML database):
它以XML文件作为其基本(逻辑)存储单位,正如关系数据库以表中的行作为基本(逻辑)存储单位。 它对底层的物理存储模型模型没有特殊要求。例如,它可以建在关系型、层次型或面向对象的数据库之上,或者使用专用的存储格式,比如索引或压缩文件。 该定义的第一部分与其他类型数据库的定义相似,都是关于数据库所用的模型的。不过,原生XML数据库所能存储的信息比模型中定义的多。例如,它可支持基于XPath数据模型的查询,但所用的存储格式是纯文本。CDATA部分和实体用法也可存储在数据库中,但是模型中没有包括。 定义的第二个部分是说原生数据库的基本存储单位是XML文件。看起来似乎也可存储XML文件片断,但几乎所有的原生XML数据库都是以文件方式存储的。 (基本存储单位就是可以容纳一份数据的最低级的上下文(context) |