级别: 中级 Kevin Williams (kevin@blueoxide.com), CEO, Blue Oxide Technologies,LLC
2003 年 7 月 01 日 XML 的重要特性之一是,可以方便地重用您的设计,该工作可以一直下至组件这一级。本文是由三部分组成的系列文章中的第一篇,专栏作家 Kevin Williams 概述了企业级解决方案中的 XML 重用,并举了一些用 XML 和 XML Schema 表示的示例。
卷首语:XML 重用之前的策略
在创建 XML 之前,序列化数据通常采用平面文件的形式(暂且将 SGML 放在一边,因为它很复杂,只有在特定的场合才会使用)。这些文件可以采用许多形式中的任何一种,最常用的是重复记录方法。在这些序列化表示中(表 1 显示了一个样本),每条记录都被定义成具有一定数目的字符,并且需要一个独立的文档来描述每条记录的内容。
表 1. 样本平面文件描述
|
起始位置
|
长度
|
名称
|
格式
|
描述
| | 1 | 30 | 姓名 | string | 客户姓名。长度不足 30 时右边用空格进行填充。 | | 31 | 10 | 余额 | numeric(10,2) | 客户余额。默认为十进制。长度不足 10 时左边用零填充。 | | 41 | 6 | 到期日 | date | 客户帐单的到期日。MMDDYY。 |
这个典型平面文件的输出类似于这样:
Kevin Williams 0000010817031103Anne Yastremski 0000007723031303
|
有关该方法的几个问题使它难于使用。例如,如果没有用于描述内容的文档,那么文件本身就难以理解。这里的示例不是十分困难 — 假定您知道这个文件是在接近 2003 年初创建的 — 但是,如果没有支持文档,那么实际上就不可能解析更复杂的文件。此外,对源文件的任何更改都将破坏为读取它而设计的任何解析器。例如,假定我向上述示例添加了两位数字,使年份变成四位数。记录长度将从 46 个字符变为 48 个字符,这时必须对每个解析器进行修改,以顾及这一更改。
除非接收系统碰巧与发送系统直接兼容(例如,两个 COBOL 系统都使用 PICS 文件描述数据),否则就很难验证文档内容 — 基本上必须
以手工方式(即利用定制代码)验证字段。最后,文档设计是通用的。如果接收系统只希望知道所有客户总的未结余额,那么将必须接收并丢弃许多无关的数据字节。
典型的 XML 重用策略
利用 XML 序列化,可以解决平面文件带来的许多问题。在 XML 领域中,文件内容的描述变成了 XML Schema,文件本身成了 XML 文档,如清单 1 所示。
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="customers">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="customer" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="customer">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="name">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:maxLength value="30"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
<xsd:element name="balance">
<xsd:simpleType>
<xsd:restriction base="xsd:float">
<xsd:totalDigits value="10"/>
<xsd:fractionDigits value="2"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
<xsd:element name="dueDate" type="xsd:date"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<customers>
<customer>
<name>Kevin Williams</name>
<balance>108.17</balance>
<dueDate>20030311</dueDate>
</customer>
<customer>
<name>Anne Yastremski</name>
<balance>77.23</balance>
<dueDate>20030313</dueDate>
</customer>
</customers>
|
让我们看看这种方法如何解决了前面提出的由平面文件带来的问题。首先,XML 文档相对而言是自描述的,因此,即使没有 XML Schema 文档,您也可以非常自信地解析这种文档。其次,序列化的结构化本质允许对文档进行更改。例如,如果您打算添加一个字段,它或许可以在不做修改的情况下接受新文件,而这取决于解析器是如何编写的。
此外,由于有了 XML Schema,文档验证现在是内置的。任何可以理解 XML Schema 文档的系统(当今的大多数系统都可以)都可以根据 Schema 中描述的约束在解析时验证数据,而无需额外的代码。不幸的是,这种设计方法不能解决最终关心的问题:通用性问题。到目前为止,大多数 XML 模式设计工作都模仿了平面文件设计人员过去所采用的方法:构建一个结构,并尝试着在所有情形下都使用该结构。如果序列化包含您不感兴趣的信息,那么您必须丢弃该信息 — 这会消耗宝贵的带宽和处理器时间。如果您想要另一种序列化,那么设计人员就得从头做起,创建一个新结构,该结构需要一个完全不同的解析器。
但是,XML 的分层特性允许您为 XML 设计采用不同方法 — 组件级重用,接下来我将研究该方法。
组件级重用:概述
可以认为 XML 文档是一组嵌套式容器。最外层的容器是根元素。根元素的所有子元素都作为容器出现在它的内部,这样层层嵌套,直到容器只包含实际的文本值。(属性可以被认为是对描述其中内容的特定容器的标签,但目前我们对此不想扯得太远)。例如,您可能拥有如图 1 和图 2 所示的结构,每个结构都包含一个
customer 元素:
图 1. 客户列表示例
图 2. 发票示例
乍一看,这些结构似乎不兼容。它们描述了完全不同的数据概念(一个描述了客户列表,而另一个描述了一张发票),并且包含不同的信息。但是,如果您为这两个文档构建两个完全独立的结构,那么您将错过一个重用机会。您或许能够在这两个文档中重用
customer 元素。但是,要这样做,两个
customer 元素在语法和语义上必须相同。它们不仅必须具有相同的内容,而且每当内容出现时还必须具有相同的含义。
您可能会说“太棒了”,所以我共享了
customer 元素。这样做有什么优点呢?组件级重用具有几个优点。让我们简要介绍其中的三点。
优点 1
首先,XML 和 XML 解析器的本质使得将您的容器(或元素)当成黑盒非常容易。换而言之,您可以获取一个您知道在别处重用的元素,并复制它,而无需担心该元素的内容。例如,假定我有一个如前面
清单 1 中所示的客户列表文档,而我希望为特定的客户创建发票。一旦我确定了客户列表中的客户元素(例如通过匹配客户标识或名称),就能方便地复制该元素以及其所有子元素,并将它复制到我的发票文档中。我无需知道
customer 元素中嵌入了其它什么信息。
customer 元素可以包含详细的地址信息、去年客户订单的汇总,甚至客户喜欢的冰淇淋的口味。至于代码则是无关紧要的。共享元素可以获得更简单、更便于管理的代码,因为将
customer 元素的内容从一个文档移到另一个文档并不需要串并转换或重新序列化。
优点 2
其次,当重用元素时,可以充分地使用典型的 XML 表示方法。因为 XSLT 以每元素为基础进行操作,从而保证了跨不同源文档的元素在语法和语义上是相同的,这使您可以重用 XSLT 样式表段。例如,假定每当我在我的网站上显示客户信息时,我希望客户姓名是粗体,地址是斜体等等。如果我将该处理代码存储在某个地方(比方说作为模板存储在
customer.xslt 文件中),那么在任何我需要显示客户信息的地方都可以在样式表中使用
xsl:include 。这样,当产品经理要求我将客户姓名由黑色文本改为藏青色文本时,我可以更改
customer.xslt 文件,它将自动应用于 Web 页面中任何出现客户的地方。
优点 3
再次,在 XML 设计中重用组件使您可以重用序列化代码。由于现在我知道
customer 元素在我的每个目标文档中都将是相同的,所以可以创建一个
Customer 对象,它带有一个可以返回 XML 文档片段的
serialize 方法。然后,每当我需要某个客户出现在 XML 文档中时(例如,作为我的发票的一部分或客户列表的一部分),我可以使用相同的代码来构建必要的元素。这种方法降低了代码冗余,并且极大地简化了故障诊断和升级工作。
结束语
在这篇专栏文章中,我讲解了如何重用 XML 设计,不仅是在文档级,而且还可以下至组件级。我向您展示了这个组件级重用的优点,以及它是如何简化代码和缩短开发周期的。在下一篇专栏文章中,我将讲解 XML 文档设计中不同类型的重用组件,并向您展示每个组件的一些实际示例。
参考资料
关于作者
对本文的评价
|