原生 XML 数据库:你为什么应该关心?





4.00/5 (4投票s)
本文档将介绍如何将 XML 文档存储在集成、可扩展、高性能、面向对象的原生 XML 数据库中,并利用其快速访问 XML 文档的每个元素的功能,无论并发用户数量、文档数量或数据库大小如何。
引言
XML 正在成为组织表达其复杂或多样化内容结构的日益普遍的格式。它便于创作,非常适合寻求开发灵活应用程序的公司。XML 的存储、操作和处理一直是个问题,而关系型数据库无法提供足够的扩展性来帮助解决这些问题。
XML 数据库(也称为原生 XML 数据库)具有显著增强 XML 管理和操作功能的功能,XML 是一种最初旨在促进不同信息系统之间共享结构化数据的数据格式,尤其是在互联网上。
XML 数据库得益于万维网联盟(W3C)制定的标准。这些标准为将 XML 数据管理服务连接到常用应用程序框架创建了强大的架构。使用和支持这些标准的 XML 数据库提供了其他数据库技术(如关系型数据库)所不具备的功能,包括高效的访问、查询、存储和处理。XML 标准以及支持它们的数据库为管理最复杂和要求最苛刻的内容应用程序提供了强大的平台。
EMC® Documentum® XML Store OEM 版:一款强大的原生 XML 数据库
EMC® Documentum® XML Store OEM 版专为需要在其应用程序中进行高级 XML 数据处理和存储功能的软件开发人员而设计。XML Store 能够对大量 XML 文档进行高速存储和处理。使用 XML Store,程序员可以构建自定义 XML 内容管理解决方案,并将 XML 文档存储在集成、高度可扩展、高性能、面向对象的数据库中。全面的 XML Store Java API 包含用于存储、查询、检索、转换和发布 XML 数据的各种方法。XML Store 可以在任何 Java 平台(JDK 1.5 或更高版本)上运行。
XML Store 提供了许多功能来帮助您处理和管理 XML 文档,包括
- 一个用于检索文档特定部分的 XQuery 引擎
- 一个版本控制机制,用于跟踪 XML 数据中的差异
- 各种索引方法,用于优化对常用 XML 数据的访问,并启用全文搜索
- 一个转换器和格式化器,用于将 XML 数据发布为 XHTML 或 PDF
- 一个改进的页面替换算法,以增强性能
您可以在此位置获取有关 XML Store 的更多信息。
基于开放标准
XML Store 使用并支持所有 XML 标准,包括 XML 1.0、XQuery、XML Schema、XPath、XSL、XPointer、XLink、XUpdate 和 DOM。这些 W3C 标准可用于访问、搜索、处理和存储 XML 数据。
XML Store 对 XML 标准的支持为内容创建和交付带来了强大的优势。例如,数据可以在异构环境中捕获、编辑和呈现。此外,文档可以被创建和管理,以便在各种用户手册中重用,并在制造等环境中的不同输出格式进行再利用。在这些文档组件大量共享和重用的环境中,标准支持强大的版本控制。最好的消息是:您现有的 XML 标准知识将使 XML Store 易于使用,让您能够快速上手。
简单易用
要开始使用,您可以从此位置下载并安装 XML Store 原生 XML 数据库产品的试用版。
创建数据库
安装 XML Store 后的第一步是创建一个数据库。最简单的方法是通过 AdminClient 完成,如下所示:
- 通过运行 XHAdmin 启动 AdminClient,它位于 Windows 上 XML Store 的 XML Store 目标目录的 bin 子目录和开始菜单组中。
- 通过选择菜单选项“数据库”->“创建数据库”来创建一个数据库。
- 创建一个名为
united_nations
的数据库,超级用户密码为安装 XML Store 时输入的密码,管理员密码为northsea
。此数据库将默认用于本文档中描述的所有示例。
创建数据库后,您可以关闭管理员客户端。请注意,您也可以使用管理员客户端在运行示例后查看数据,并执行其他操作。或者,可以使用命令行工具 XHCreateDB
来创建数据库。
运行示例
XML Store 示例使用 ant 构建系统运行。提供了一个名为 xhive-ant
的命令行工具,该工具设置了正确的 CLASSPATH
和其他参数。示例的运行方式如下:
- 打开命令提示符,然后转到 (cd) XhiveDir\bin 目录。
- 要运行一个将两个文档插入数据库的示例,请键入命令:
xhive-ant run-sample -Dname=manual.StoreDocuments
- 示例成功完成后,将显示一条消息,说明数据库中存储的文档数量。
所有示例的源代码可以在 XhiveDir\src\samples\manual 中找到。在运行示例之前,您应该检查 SampleProperties.java 中属性的值,使其与您的设置匹配。
解析 XML 文档
要从外部源导入 XML 文档,需要解析该 XML 文档。您可以使用 DOM Load / Save LSParser 接口的 parseURI
方法来解析文档。
XhiveLibraryIf
接口扩展了 DOMImplementationLS
,可用于创建 LSParser
和 LSSerializer
对象。您必须在要存储文档的库上创建 LSParser
。
当解析成功时,将返回一个 DOM Document。
LSParser builder = rootLibrary.createLSParser();
Document firstDocument = builder.parseURI( new File(fileName).toURL().toString());
要将解析后的文档存储到数据库中,您还需要执行显式的 appendChild
。否则,文档仅被解析而不会被存储。
解析文档示例使用默认的 LSParser
配置设置。
XML Store 支持 DOM Load/ Save 规范,该规范提供了解析和序列化 DOM 的标准方法。
存储 XML 文档
要将 XML 文档存储在 XML Store 数据库中,请使用 appendChild()
方法。在使用 appendChild()
方法之前,您需要获得要存储文档的库的句柄。每个数据库默认都有一个根库。要将文档存储在示例数据库的根库中,您可以使用以下代码
XhiveLibraryIf rootLibrary = united_nations_db.getRoot();
rootLibrary.appendChild(firstDocument);
或者,您可以使用 insertBefore()
方法存储文档,这也是一个标准的 DOM 方法。使用 insertBefore()
指定的第二个参数是您希望在它前面插入新文档的文档。
rootLibrary.insertBefore(secondDocument, firstDocument);
导入非 XML 数据
XML Store 可以从非 XML 文件导入数据,前提是您提供有关数据字段在源文件中如何分隔和排列的信息。com.xhive.util.interfaces.XhiveSqlLoaderIf
接口包含用于导入非 XML 数据的方法。有关这些方法的详细说明,请参阅 XhiveSqlLoaderIf
Javadoc。
在此示例中,数据以 CSV 格式导入到 XML Store,并存储为 XML 文档。要导入的数据如下所示:
"Member", "Date of Admission", "Additional Notes"
"Iceland", 19 Nov. 1946, ""
"India", 30 Oct. 1945, ""
"Indonesia", 28 Sep. 1950, "By letter of 20 January ..."
"Iran (Islamic Republic of)", 24 Oct. 1945, ""
您可以使用 XhiveSqlLoaderIf
对象,通过 loadSqlData()
方法导入数据
Document un_members_doc = loader.loadSqlData(Impl,
FileName,
',',
'\\',
'"',
true,
"UN_members",
XhiveSqlLoaderIf.IGNORE_HEADER,
"member",
new String[] {"name","admission_date","additional_note"},
new Boolean[] {false, false, false});
创建文档
XML 数据以文档的形式存储在 XML Store 数据库中。文档在 XML Store API 中由 org.w3c.dom.Document
接口表示。此接口包含许多用于创建新 XML 文档、更新 XML 文档(部分)以及访问文档(元素、注释、属性等)部分的方法。
要创建一个新文档
-
获取 DOM 实现的句柄(通过
rootLibrary
作为XhiveLibraryIf
扩展DOMImplementation
) -
DOMImplementation impl = rootLibrary;
-
使用
org.w3c.dom.DOMImplementation
中的createDocument()
方法创建一个DocumentType
和一个Document
。 -
DocumentType docType = impl.createDocumentType("typeName", "publicId", "systemId");
-
Document eventsDocument= impl.createDocument(null, "events", docType);
由于没有使用namespaceURI
,第一个参数可以留空。createDocument()
的第二个参数events
是根元素的(标签)名称。第三个参数设置新文档的docType
。 -
获取新创建文档的根元素的句柄
-
Element rootElement = eventsDocument.getDocumentElement();
-
您现在可以使用标准的 DOM 方法添加文档部分。这些方法位于
org.w3c.dom.Document
接口中。最常用的方法是:createAttribute()
createComment()
createElement()
createTextNode()
以下代码向新文档添加一个注释、一个名为 event
的元素,该元素具有属性 occurrence
,以及一个(文本)值 "UNICEF, Executive Board, annual session"
。
// add a comment to the document before the root element
Comment comment = eventsDocument.createComment("this document contains UN
events");
eventsDocument.insertBefore(comment, rootElement);
// add a new element to root element
Element eventElement = eventsDocument.createElement("event");
rootElement.appendChild( eventElement );
// add text value to the element
Text eventText =
eventsDocument.createTextNode("UNICEF, Executive Board, annual session");
eventElement.appendChild(eventText);
// add an attribute to the element
eventElement.setAttribute("occurrence", "year");
要将值为 "4-8 June, 2001"
的 date
元素添加到 event
元素中,请使用以下代码:
// add a new element to event
Element dateElement = eventsDocument.createElement("date");
eventElement.appendChild( dateElement );
// add text value to the date element
Text dateText = eventsDocument.createTextNode("4-8 June, 2001");
dateElement.appendChild(dateText);
这是生成的 XML 文档:
<!DOCTYPE typeName PUBLIC "publicId" "systemId">
<!--this document contains UN events-->
<events>
<event occurrence="year">
UNICEF, Executive Board, annual session
<date>4-8 June, 2001</date>
</event>
</events>
一如既往,要将文档实际存储到数据库中,您需要使用 appendChild()
或 insertBefore()
方法。
rootLibrary.appendChild(eventsDocument);
执行查询
您可以使用 XhiveNodeIf
接口上的 executeXQuery(String query)
方法执行 XQuery 查询。它返回一个表示结果序列的迭代器。结果的每个元素都是 XhiveXQueryValueIf
的实例。在 XML Store for Java 5(JDK 1.5 及更高版本)中,所有迭代器和结果也都使用新的模板语法进行类型化(例如,executeXQuery(String)
返回 Iterator<XhiveXQueryValueIf>
)。
XhiveNodeIf lc = ... ;
Iterator result = lc.executeXQuery("doc('doc')//item");
while (result.hasNext()) {
XhiveXQueryValueIf value = (XhiveXQueryValueIf)result.next();
// We know this query will only return nodes.
Node node = value.asNode();
// Do something with the node ...
}
在查询中,上下文项(可通过 .
访问)最初绑定到执行查询的节点。示例(Java 1.5 语法):
XhiveNodeIf node = ...;
Iterator<XhiveXQueryValueIf> result = node.executeXQuery("./author/first,
./author/last, ./contents");
for (XhiveXQueryValueIf value : result) {
// do something with the value ...
}
如果您只想显示结果,可以使用返回值的 toString()
方法,而不管其类型。
XhiveLibraryChildIf lc = ... ;
String query = ... ;
Iterator result = lc.executeXQuery(query);
while (result.hasNext()) {
System.out.println(result.next().toString());
}
如果查询使用节点构造函数,则创建的任何节点都将在临时文档中创建。如果需要,可以使用 DOM importNode()
方法将这些节点插入另一个文档。
如果您想将节点插入到特定文档中,可以在调用中指定新节点的拥有文档。这比创建临时文档并将其节点导入目标文档更有效。
XhiveLibraryChildIf lc = ... ;
XhiveDocumentIf doc = ... ; // Create new nodes in this document
Iterator result = lc.executeXQuery("<count>{count(//item)}</count>", doc);
// We know this query will only return a single node.
XhiveXQueryValueIf value = (XhiveXQueryValueIf)result.next();
Node node = value.asNode();
// Append it to the document element of destination document
doc.getDocumentElement().appendChild(node);
查询结果是惰性评估的,也就是说,每次调用结果迭代器上的 next()
时都会进行评估。请注意,在(同一会话中)修改搜索文档或库后,不要调用 result.next()
。如果这样做,可能会出现未定义的结果。如果您想使用查询输出来修改搜索文档,请使用 xhive:force()
函数或更新语法(见下文)。
全文搜索
X-Hive 将 XQuery 扩展为支持全文搜索功能。全文搜索功能可用于搜索文本字符串中的术语。一般来说,您可以将“术语”视为单词。例如,字符串 "yadda yadda yadda"
包含三个术语,每个术语的值为 "yadda"
。在 X-Hive 中,术语是全文索引和搜索的基本单位。这与 XQuery 中的 contains
函数不同,后者将文本视为一个单一的整体字符串。使用全文搜索函数有许多优点,因为全文搜索函数
- 将输入字符串视为术语列表,而不是像
contains
函数那样视为字符列表。这使得索引的使用更加实用。目前,在使用contains
函数时不会使用任何索引。然而,全文搜索可以使用索引。 - 允许使用通配符和前缀。
- 允许您搜索精确或模糊的短语。
全文搜索函数声明如下:
xhive:fts(node(s), querystring, options)
函数的第一个参数应该是节点(集)。第二个参数期望是一个查询字符串。如果第一个参数提供了一组节点,则在所有节点上执行全文搜索。选项参数是可选的,(如果存在)应为包含分号分隔的选项列表的字符串文字。
结果是一个布尔值,如果文本与查询匹配,则返回 true
。
有一个名为 include-attrs
的选项。使用此选项时,当您在元素上执行函数时,该元素(及其后代)的属性值会与文本节点一起被评估。请注意,如果您想将 include-attrs
选项与全文索引结合使用,则必须在该索引上使用 FTI_INCLUDE_ATTRIBUTES
选项(反之亦然,如果您不使用 include-attrs
,则不能在索引上设置该选项)。
全文搜索查询语法
全文搜索查询的语法如下:
Query ::= Clause ( [ Conjunction ] Clause ) *
Conjunction ::= 'AND' | 'OR' | '||' | '&&'
Clause ::= [ Modifier ] BasicClause [ Boost ]
Modifier ::= '-' | '+' | '!' | 'NOT'
BasicClause ::= ( TermQuery | Phrase | '(' Query ')' )
TermQuery ::= ( Term | WildCardTerm | PrefixQuery ) [ Fuzzy ]
PrefixQuery ::= Term '*'
Phrase ::= '"' Term * '"' [ SlopFactor ]
Fuzzy ::= '~'
SlopFactor ::= '~' DecimalDigit+
Boost ::= '^' DecimalDigit+ '.' DecimalDigit+
Term ::= <a-word-or-token-to-match>
WildCardTerm ::= <a-word-or-token-to-match-with-wildcards>
以下字符是保留字符,如果未使用任何特殊含义,则需要用反斜杠 (\
) 进行转义:+
、-
、!
、(
、)
、:
、^
、[
、]
、"
、{
、}
、~
、*
、?
结论
您可以在各种架构中使用 XML Store,例如独立式、客户端-服务器和 SOA。XML Store 可以在任何支持 Java 的平台(JDK1.4 或更高版本)上运行,包括 Sun Solaris、HP UX、Linux、Windows 和 Macintosh。为确保与现有应用程序和系统的顺畅快速集成,XML Store 提供了:
- 与关系型数据库的接口
- 与 XML 编辑器和全文搜索引擎的桥梁
- 对 J2EE 和 WebDAV 的支持