级别: 中级 William von Hagen, 系统管理员,作家, WordSmiths
2009 年 6 月 29 日 探索一个重用 XML 文档中的信息的简单解决方案,比如如何使用 XInclude 在特定点包含其他文档,以及如何使用 XPointer 从其他文档(或类似的 XML 格式的信息集)包含文档片段。此外,获取通过构建 XML 文档简化信息重用的技巧,并学习如何维护可以添加到更大文档中的独立文档。
重用信息
如我在本系列的 在 XML 内生成文档并重用信息,第 1 部分:利用 XML 发布文档 所述,Standard Generalized Markup Language (SGML) 是 XML 的前身。SGML 的主要目的是将文档的内容(文档包含的实际文字和数据)与表示(内容以特定输出格式显示的方式,或在特定输出设备上显示的方式)分离开来。通过使用称为标记 的特殊符号来标识包含在文档中的信息的结构和类型,您可以更多地关注文档的内容,而不是信息最终是如何使用和表示的。在 XML 中以通用的格式呈现结构化信息(不受使用信息的方式影响)甚至更加重要,因为通用的格式不受限于文档领域。
 |
常用缩略词
- DTD:文档类型定义
- W3C:万维网联盟
- XML:可扩展标记语言
|
|
在文档领域中,以基于文本的结构化格式维护信息的一个重要影响是,XML 信息不依赖于任何特定的软件包。您可以使用各种应用程序处理 XML 文档,包括从文本编辑器到复杂的图形工具等。然而,合理的结构化标记的一个更加重要的影响是,它使您能够轻松地在任何支持信息结构的上下文中重用该信息的任意部分。
 |
DITA
其他 XML 文档解决方案(比如 Darwin Information Typing Architecture (DITA))提供类似的灵活性,其目的也是在 XML 文档环境中简化信息的重用。DITA 需要将正在编写和管理的信息分成大量片段,这可能不可行或不好管理(取决于职员和软件需求),但是确实可以考虑用它替换本文讨论的更加传统的、关注 DocBook 的解决方案。
|
|
根据结构化文档的定义,它在逻辑上包含多个子部分:书本由章节构成,章节由多个段落构成 —— 它们都是以特定的顺序表示的。像编程概念一样(比如模块化编程),将文档想象成多个分开的信息逻辑单元,这是为正在编写任务提供结构的好方式。如果您分开存储每个逻辑信息单元(称为 块),并且能够以特定的方式将它们组织成文档,那么这个模型还为信息重用提供一个良好的基础。
为了支持从分开的子文档创建大文档,XML 提供一个基础机制,即 XInclude,用于将外部 XML 文件包含到一个 XML 文档中。这个机制为使用在多个文档中维护的或位于同一个文档的多个地方的信息块提供便利。不过,如下一小节所示,XML 为重用来自其他 XML 文档的信息提供几种机制,并且每种机制适合不同的场景。
XML 内容包含机制
XML 就像之前的 SGML 一样,最初都是通过声明实体(在 XML 中称为 XML 外部实体)的方法将文档包含到其他文档中。实体为需要包含的特定文件提供一个逻辑名。外部实体的基础语法是:
<!ENTITY name [PUBLIC "public-identifier"]
SYSTEM "system-identifier">
|
name 就是与 system-identifier 关联的逻辑名,system-identifier 是您调用实体时希望插入到文档中的 XML 文件的统一资源定位符(URI)。PUBLIC 关键字和 public-identifier 都是可选的,如果您的系统支持公共标识符的话,这允许您使用更加灵活的、独立于位置的 URI 定位实体。下面是 XML 外部实体定义的一个好例子:
<!ENTITY chapter1 SYSTEM "chapter1.xml">
|
如果您希望通过外部实体引用的文件不是 XML 文件,您必须在系统标识符之后指定该文件的格式,下面是一个使用 PNG 文件的例子:
<!ENTITY figure1 SYSTEM "figure1.png" PNG>
|
符号标识符的目的是让 XML 处理或格式系统更容易找到 helper 应用程序,该应用程序将处理与符号相关的文件的类型。
外部实体很方便,但也有一些限制。对重用信息而言,最明显的限制包括:
- 由外部实体标识的 XML 文件仅能包含文档片段:它不能包含
DOCTYPE 声名或独立的 XML 声明。这意味着一个外部实体不能引用其他外部实体,因此外部实体的功能仅限于 include 机制。
- 您不能仅包含外部实体标识的 XML 文件的一部分。这意味着您必须包含希望重用的、位于多个文档或文档位置的所有信息。
这些局限最终导致提议构建更灵活和通用的 XML 包含机制(XML Inclusions,更常见的称呼是 XInclude),XInclude 由 IBM® 和 Microsoft® 于 1999 年提交给 W3C。W3C 于 2004 年接受了这个提议,并作为建议发布。现在,XInclude 已是第二个版本,并且在 2006 年作为建议发布。
XInclude 建议为包含外部信息指定了两种不同的方法:
- 标识希望完整包含的外部资源的位置(URI)。这通常称为简单 XInclude 语句。
- 标识包含在外部资源中并且可以转移到另一个 XML 文档的独特 XML 信息块。为此,需要使用一个带有特定属性的 XInclude 语句(这些属性指定包含需要包含的信息块的外部资源的 URI),一个指定该目标 URI 并指向可解析 XML 文档的属性,以及一个在希望包含的资源中标识 XML 元素的
xpointer 语句。这种方法通常简称为 XPointer,实际上,它是 XPath 规范 的一个扩展的名称,这个规范关于如何标识 XML 文件中的信息。
对于这两种包含重用信息的方法,第一种通常用于处理更大的信息块,不管是作为独立文档还是作为包含文档维护;而第二种方法则能够非常便捷地从这些文档中提取相对较小的信息块。
是包含整个外部资源还是仅从外部资源提取一小部分信息块,这取决于您如何组织所管理的信息块,以及您需要重用的信息的类型。
在讨论如何获取支持 XInclude 和 XPath(同时也会包含 XPointer)的开源软件之后,本文接下来的内容将解释如何使用 XInclude 和 XInclude/XPointer 包含外部信息,并且讨论最适合使用它们场景。
获取和安装所需的软件
几乎所有 XML 文档软件都支持 XPath 和XInclude,本文主要关注支持这些规范的开源 XML 解决方案。最著名的 XML 处理开源包是 xsltproc,当您指定 --xinclude 命令行选项时,它就支持 XPath 和 XInclude 处理。查看 参考资料 部分了解从哪里获取 xsltproc 包。
如果您使用的是 Linux® 系统(或按照本系列 在 XML 内生成文档并重用信息,第 1 部分:利用 XML 发布文档 设置了 XML 文档处理环境),您的系统可能已经安装了 xsltproc 实用程序,或者至少可以从您的发行版的储存库或安装媒体库中获得。
要确定您的系统是否已经安装 xsltproc,请执行以下命令:
如果 xsltproc 应用程序已经安装在您的系统上,并且执行路径正确,您应该看到运行的命令的版本信息。
使用 XInclude 包含外部信息
XInclude 建议的核心是 include 语句,它使您能够将其他 XML 文档包含到给定文档中,而这个过程仅需一个最基础的 XInclude 语句:
<xi:include href="../common/tutorial1.xml" />
|
href 属性是一个可选值,它提供需要包含的资源的 URI。
从这个例子可以看到,include 语句位于它自己的名称空间中(xi)。为了在文档中使用 include 语句,并且不在文档工具中生成错误或警告消息,请声明 xi 名称空间。将定义该名称空间的属性添加到您正在创建的文档类型的根节点:
<?xml version='1.0'?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">
<book xmlns:xi="http://www.w3.org/2003/XInclude"
id="product-usersguide">
|
在添加这个声明和一个或多个 xi:include 语句之后,您应该就能够使用文档工具处理主文档,以及将特定文件插入到指定点。
许多文档工具不认为包含文档失败是严重错误,这会导致一些非常短的文档。为了提供一种方法来检测失败的 xi:include 语句,XInclude 规范提供了 fallback 语句。这个语句仅在 xi:include 语句内部有效,如果包含失败,它就用自带的文本替换 xi:include 语句。下面是一个带有 xi:fallback 语句的简单 xi:include 语句:
<xi:include href="../common/tutorial1.xml">
<xi:fallback>FATAL ERROR - BROKEN INCLUDE!</xi:fallback>
</xi:include>
|
这个例子将在 XML 输出中嵌入一个字符串 FATAL ERROR - BROKEN INCLUDE!。您可以直接查看,也可以编写检查脚本,发现这个字符串时停止文档处理。
使用 XPointer 包含外部信息的一部分
如前所述,XPointer 是 XPath 规范的一部分,并且得到 XInclude 规范的支持。在 include 语句中使用 xpointer 属性使您能够提取外部 XML 资源的一部分,然后将其插入到另一个文档的当前位置。在 XInclude 语句中使用 XPointer 的最常见情况是,您希望提取和重用包含在另一个文件中的一小部分信息。这为将所有可包含的外部信息作为独立的外部资源管理提供一种易于使用的代替办法。
使用 xpointer 属性的 include 语句的最基本语法是:
<xi:include href="../common/glossary.xml" parse="xml"
xpointer="element(para)xpointer(//glossentry[@id='caching']/glossdef/*)"
/>
|
这个例子提取 XPath 语句 //glossentry[@id='caching']/glossdef/ 指向的段落(para)元素,它是 ID 为 caching 的词汇条目的 glossdef 元素的内容。
词汇表是最常见的例子。在词汇表中,我们通常希望在一个文件资源中维护许多不同的信息单元,同时我们还希望能够提取该信息的一部分,以在文档的其他地方或另一个文档中重用它们。
组织 XML 文档以供重用
当您要包含另一个文档中的外部 XML 资源时,最值得考虑的地方是,这些资源的语法在包含它们的点上必须是有效的。因此,在创建 XML 数据或重构现有 XML 数据时必须进行一些规划。
通过包含简化重用的一个关键点是,在希望包含的文档片段中尽可能使用最通用的标记。例如,DTD 和模式(比如 DocBook)提供 section 元素,该元素在文档上下文中使用显式的和派生的层次结构。显式 section 元素包括 <sect1> 和 <sect2> 等。使用等效的通用 <section> 元素(从它出现的上下文中派生出自己的层次结构)为信息重用提供更加灵活的模型,因为它可以被重用并且在很多级别上都是有效的。
重用那些既希望包含又希望生成为独立文档的外部资源要复杂一些,但是自动化该过程很容易。您可以将它们作为可包含的片段维护,并放到一个包含 XML 文章声明及其基础框架的简单包装器文档中;或者将它们作为独立的文档维护,并且在实际包含它们之前动态地将其转换为可包含的资源。
例如,您可能将一份教程作为类型为 article 的独立 DocBook 文档维护,这样您就可以独立的打印它,并让它自动生成一个目录表。您可能还希望将该教程包含到另一个更大的独立文档中(比如一本书),但是文章(article)在书本(book)上下文中是无效的。DocBook 文章以以下形式声明开始:
<article xmlns:xi="http://www.w3.org/2003/XInclude"
id="tutorial1">
<articleinfo>
<title>
Tutorial: Using Emacs
</title>
</articleinfo>
|
为了将这个声明转换成一个可包含文档,您可以编写一小段脚本或一组 Makefile 规则将其转换为:
<section xmlns:xi="http://www.w3.org/2003/XInclude"
id="tutorial1">
<title>
Tutorial: Using Emacs
</title>
|
下面是一个样例 Makefile 条目,它所做的事情是一样的:
cat tutorial1.xml | grep -v articleinfo | \
sed -e 's;<article;<section;' \
-e 's;</article>;</section>;' > tutorial1-includable.xml
|
当希望将该文档生成为独立的文章时,您可以处理 tutorial1.xml 文件。当希望将该文档包含为另一个文档的一部分时,您可以像本例一样调用一个 Makefile 文件,然后使用一个 <xi:include> 语句包含 tutorial1-includable.xml 文件。
结束语
在本文中,您探索了一个关于在 XML 文档中重用信息的简单解决方案,以及如何使用 XInclude 包含外部文档,使用 XPointer 包含其他文档的片段。
今天的企业信息需求和产品要求使用丰富的文档集,这些文档在不同的上下文中使用相同的信息。在多个文档和文档上下文中使用分开的信息块可以减少文字输入,并且可以避免在多个地方维护相同的信息。将文档内容划分为多个可标识的信息单元可能会增加需要管理和维护的文档文件。不过,对大多数文档组而言,一致性能够节省时间和保持准确,尤其是管理大型文档集时,其益处是非常明显的。
参考资料 学习
获得产品和技术
讨论
关于作者  | |  | William von Hagen 担任 UNIX 系统管理员已经超过 20 年,并从 1993 年开始成为 Linux 爱好者。Bill 是一些图书的作者或合著者,涉及的主题包括 Ubuntu Linux、Xen Virtualization、GNU Compiler Collection (GCC)、SuSE Linux、Mac OS X、Linux 文件系统和 SGML。他还为 Linux 和 Mac OS X 出版物和网站撰写了许多文章。 |
对本文的评价
|