级别: 中级 Kevin Williams (kevin@blueoxide.com), CEO, Blue Oxide Technologies,LLC
2003 年 3 月 01 日 在上一篇专栏文章中,Kevin Williams 说明了 XML 设计中的组件级重用如何减少代码复杂性以及如何缩短维护周期。在这个系列(由三篇文章组成)的第二篇文章(也就是本文)中,笔者描述了 XML 设计中可重用的组件类型,并以 XML 和 XML Schema 提供了每种组件的示例。请在与本文附带的论坛中提出您对文本的想法,以飨笔者和其他读者。
既然我已说明了在 XML 文档设计中使用组件级重用的
原因,那么接下来我将着手研究重用
什么。了解 XML 文档中可以重用的组件类型(以及这样做的好处)将有助于您辨别出合适的重用机会,从而能够利用这些机会。
注释:由于在 XML 领域有很多专用术语,因此在这篇专栏文章中,我有意识地选择一些术语,而它们不直接与
XML Schema 构造、DTD 构造或 XML 领域中其它任何术语一一对应起来。当我需要引用 XML 领域中的某些术语时,我会明确地说明(例如,我会说“XML Schema
complexType ”,而不会说“
complexType ”),这仅仅是为了避免任何混淆。
数据类型
您可以重用的最基本的设计构造是数据类型。数据类型通常是取自 XML
Schema 中某一个内置数据类型(或其它用户定义的数据类型),并按某种方式对该数据类型进行限制。例如,我可能有一个用于“部件号”的数据类型,它类似于:
清单 1. 用于部件号的数据类型
<xsd:simpleType name='PartNumberType'>
<xsd:restriction base='xsd:string'>
<xsd:pattern value='[0-9]{2}-[0-9]{4}' />
</xsd:restriction>
</xsd:simpleType>
|
那些具有该数据类型的文本(text-only)元素或属性必须采用我为“部件号”指定的格式 — 换句话说,采用两位数字加一个连字符再加四位数字这种格式。
另一个示例可能是类似于如下的“利率”数据类型:
清单 2. 利率数据类型
<xsd:simpleType name='rateType'>
<xsd:restriction base='xsd:decimal'>
<xsd:totalDigits value='7' />
<xsd:fractionDigits value='4' />
</xsd:restriction>
</xsd:simpleType>
|
在这种情形下,对于类型为
rateType 的文本元素或属性,它的格式必须符合小数点左边不超过三位数字,而且小数点右边不超过四位数字。
要注意的是,数据类型可以重叠,这很重要。例如,我们可能有下面两个声明:
清单 3. 重叠的数据类型
<xsd:simpleType name='cityType'>
<xsd:restriction base='xsd:string'>
<xsd:maxLength value='30' />
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name='lastNameType'>
<xsd:restriction base='xsd:string'>
<xsd:maxLength value='30' />
</xsd:restriction>
</xsd:simpleType>
|
使用“姓”数据类型的“姓”声明示例类似于这样:
<xsd:element name='customerLastName' type='lastNameType' />
|
虽然一开始您可能觉得这种方法似乎多余 — 两个数据类型具有完全相同的 base 和 restriction — 但实际上它具有两个优点。第一个优点,该方法具有可以在修改其中一种类型时不影响另一种类型这样的灵活性。所以,如果对于“姓”来说,30 个字符不够用,但对于“城市”30 个字符仍然够用,那么您可以更改“姓”数据类型而不影响“城市”数据类型。第二个优点,通过名称本身可以表明语义信息,聪明的程序员在编写代码时会利用这一点来区别这两种类型。例如,您可能编写了一个使用模式的
XSLT 生成器,产生一个样式表来将那种模式的实例以 XML 表示。在那种情形下,生成器仅仅通过数据类型就可以区分“城市”和“姓”,从而可以用不同方式来表示这两者。在我的下一篇专栏文章中,您会看到这项技术的示例。
枚举
在 XML Schema 中枚举与其它数据类型放在一起处理,但它又与其它数据类型不一样,所以值得我们对其单独进行讨论。
枚举是某个特定文本元素或属性的可允许值的列表。典型的示例是美国所有州的列表。下面这个示例定义了美国诸州的枚举(为简单起见,我省略了大多数州):
清单 4. 美国诸州的部分枚举
<simpleType name='stateEnum'>
<restriction base='xsd:string'>
<enumeration value='AK' />
<enumeration value='AR' />
<enumeration value='WV' />
<enumeration value='WY' />
</restriction>
</simpleType>
|
具有这种类型的文本元素或属性必须具有这里显式定义的其中一个值。这样做的好处很明显;如果州的列表在某处发生变化,则只需要更改一处即可。然后,该更改会反映到具有该类型的所有文本元素或属性。
数据点
数据点是文本元素或属性。它们是 XML 文档中的
值。由于文本元素和属性具有同样类型的可允许值,因此在这里我把它们放到了一个数据点存储桶中。
插一句题外话,在数据世界里(请记住本专栏的名称!),文本元素和属性可以有效地互换 — 在使用基于文本的
XML(譬如,一段标记文本)时,这些差异尤为重要。您可以在两类文档设计中利用数据点重用。
可重用的数据点声明看上去十分类似于可重用的数据类型声明:
清单 5. 可重用的数据点声明
<xsd:simpleType name='lastName'>
<xsd:restriction base='xsd:string'>
<xsd:maxLength value='30' />
</xsd:restriction>
</xsd:simpleType>
|
区别在于,在 XML Schema 中,使用
ref
属性来引用这些可重用的数据类型,而不是使用
name 和
type 属性:
<xsd:element ref='lastName' />
|
为什么要有这种区别?唔,这种差异在针对其它平台的数据设计工作(譬如关系数据库)中也始终存在。这里也存在一些语义上的差异:可重用的数据点断言两个元素的值具有相同的语义含义,而可重用的数据类型只断言它们的值空间具有相同的语义。我将在下一篇专栏文章中详细讨论这一点。
结构
结构聚集了其它结构和数据点。这里我没有使用术语
元素,因为在 XML 实例中元素也可以是数据点。可重用的结构被声明为 XML Schema 的复杂类型:
清单 6. 可重用的结构
<xsd:complexType name='Address'>
<xsd:sequence>
<xsd:element name='address1' type='xsd:string' />
<xsd:element name='address2' type='xsd:string' minOccurs='0' />
<xsd:element name='city' type='xsd:string' />
<xsd:element name='state' type='stateType' />
<xsd:element name='postalCode' type='postalCodeType' />
</xsd:sequence>
</xsd:complexType>
|
重用该结构的元素类似于这样:
<xsd:element ref='Address' />
|
结构重用确实可以极大地影响编码 — 如果您希望在整个系统中以一种方式表示“地址”,那么可以编写一个样式表片段来处理这些“地址”(因为您知道在任何地方它们都将是相同的)。然后,当需要更改“地址”的外观时,只需要更改一处即可。
高阶重用:操作、服务和流
当您登上重用“食物链”的更高层时,XML Schema 就退出了舞台,而 Web 服务进入了我们的视野。这有点超出了本专栏所要讨论的范围,但我只想提一下高级构件 — 操作、服务甚至组合流 — 都可以构建在这些可重用构件之上。例如,您可能定义
getQuote 操作,它获取
tickerSymbol 数据点(经过重用的)作为其输入,并返回
stockInfo 结构(经过重用的)作为其输出。然后,服务可能在某个特定的端点采用特定的绑定来实现
getQuote 操作(经过重用的)。
结束语
XML 设计可能会很复杂且繁琐。随着 XML 设计在整个企业中的快速增长,如果您不花些时间来预先了解如何重用这些设计构件,就会感到相当头痛。虽然好的重用方法不一定解决整个应用程序的设计需求,但大多数设计工作可能可以利用某些已有的结构、数据类型和枚举,然后仅仅添加那些特定于某个任务的组件即可。在下一篇专栏文章中,我将向您展示一些在企业中实现这些可重用组件的方法。
参考资料
关于作者
对本文的评价
|