在列表中添加新值是一种常见而且必要的需求。模式设计者通常希望在系统架构中构建一种添加附加值的方法,并且该附加值在设计阶段是未知的。模式设计者如何创建一个可扩展、易于实现的枚举值列表?本文将介绍几种实现这一目标的方法。
<!--START RESERVED FOR FUTURE USE INCLUDE FILES--><!-- include java script once we verify teams wants to use this and it will work on dbcs and cyrillic characters --><!--END RESERVED FOR FUTURE USE INCLUDE FILES-->
模式设计者和实现人员需要一种扩展 XML 模式中现有枚举列表的方法。不幸的是,XML 模式规范不允许在这些列表的创建过程中(参阅 参考资料)进行扩展。设计阶段所选的值是固定的,而且都是可用的。尽管有这样的限制,人们仍使用各种替代方案来实现列表扩展。很多使用现有的不能改变的模式的客户经常提出这一要求。他们希望在添加新功能的同时保持向后兼容性。本文中,您将会看到模式设计者如何克服障碍实现该功能。
枚举列表 是特定数据点的一组指定值。例如,您也许通过固定的值列表查看国家代码,包括 DE(德国)、US(美国)和 JP(日本)。根据给定的值集,当一个新国家被识别出时,如 TL(东帝汶)或者 BA(波斯尼亚及黑塞哥维那),该怎么办?使用以前的名称列表的客户必须改变实现来容纳新值。
当使用 XML 模式对数据建模时,枚举值被显式列出。因此,国家代码列表依次包含各个枚举值。经常需要识别列表中的新值,而且必须将其容纳到列表中,模式设计者试图找到一种扩展列表的方法,实际上,是将这种方法构建到设计中,允许添加在设计时未知的附加值。
创建可扩展的枚举列表
在寻找这一问题的解决方案时,受到四个关键标准的影响:
- 首先,要在设计阶段之后扩展列表。不管是快速建立一个新的贸易伙伴还是建立时间关键型的新数据字段,在关键时刻进行扩展是一项实际需求。
- 其次,能够在解析器中验证值对于简化实现是非常关键的。
- 第三,在单个周期内完成解析和验证是至关重要的。这就避免了像 Genericode 解决方案一样,在一个单独的周期和解析器中进行验证。对于某些设置来说,添加新技术需求会导致成本太高或者太耗时。
- 最后,解决方案必须能够向后兼容原始的模式。不兼容的列表更改不能称为扩展。
有些人认为根本就不应该扩展枚举列表。数据建模人员也许认为如果想让模型包含更多数据、扩展模型,那么可以根据产品创建模式 — 实际上,在需要时创建更大的模型并减少限制。如果能够控制原始模式和数据模型,这样做是可以的,这种方法也许是理想的方法。但是,如果您需要在设计阶段之后进行实际扩展,这样的方法是行不通的。
还有人认为扩展枚举列表的关键是不使用 XML 模式验证解析器。Genericode(参阅 参考资料)建议在第二层对枚举列表进行验证,脱离初始的 XML 模式解析器验证过程。这种理论是正确的,而且这种方法的应用会越来越广泛。但是,如果要在一个解析周期内完成,这种解决方案是无法做到的。在某些情况下,不可能执行第二个验证周期。
当然,您可以在新列表中创建新元素。但是,不能向后兼容原始模式。我们的目标是在保持向后兼容性的同时实现一个可扩展的列表(参阅 参考资料)。
对于本文的目标,这里作出的假设基于我与客户打交道的经验 —— 即用附加值扩展现有枚举列表的需求。另外,我假设在一个步骤内完成 XML 模式解析与验证等操作。
扩展枚举列表的必要条件
该扩展示例有四个必要条件:
- 允许在设计阶段之后扩展枚举列表。
- 用解析器验证枚举列表。
- 在一个周期内验证枚举列表。
- 维持和原始模式的向后兼容性。
举例来说,一个团队需要处理一个区域产业协会的枚举列表(或任意现有列表)为例,并根据使用修改模式组件。先前的模式提供 MaritalStatus
组件和值的枚举列表,如 清单 1 所示。
清单 1. 婚姻状况枚举列表
<xsd:simpleType name="MaritalStatusEnumType">
<xsd:restriction base="xsd:normalizedString">
<xsd:enumeration value="Divorced"/>
<xsd:enumeration value="Married"/>
<xsd:enumeration value="NeverMarried"/>
<xsd:enumeration value="Separated"/>
<xsd:enumeration value="SignificantOther"/>
<xsd:enumeration value="Widowed"/>
<xsd:enumeration value="Unknown"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:element name="MaritalStatus" type="MaritalStatusEnumType"/>
|
假设一个公司要使用这些值,另外,还要支持它的重要贸易伙伴使用另一个值。CivilUnion
是一个扩展值,公司识别出该值不属于原始模式。但是从语义上来说,使用现有元素 —MaritalStatus
— 也是可以的。公司要如何实现呢?
解决方案 1: 编辑原始模式使其包含新枚举值
当然,编辑原始模式使其包含新枚举值是最直接的方法。保留模式的本地副本,然后编辑这些模式以支持公司使用的枚举值。
-
优点:易于实现
-
缺点:
- 需要编辑原始模式,这些模式将逐渐改变,以至于无法控制。如果扩展一个先前存在的列表,那么创建者(贸易伙伴、协会等)可能要发布列表的新版本。您需要将编辑的内容传播到每个新版本中。
- 手动编辑模式会导致意外的编辑错误。
如果您不能(或不想)编辑原始模式,则需要一种替代方法。
解决方案 2: 创建新枚举列表并加入到原始列表中
第二个选择是创建新枚举列表,并将其加入到原始枚举列表中。清单 1 显示原始婚姻状况列表。清单 2 显示最新创建的枚举列表。
清单 2. 新婚姻状况枚举列表
<xsd:simpleType name="MyExtMaritalStatusEnumType">
<xsd:restriction base="xsd:normalizedString">
<xsd:enumeration value="CivilUnion"/>
</xsd:restriction>
</xsd:simpleType>
|
使用 <xsd:union>
标记将其与原始列表结合,如 清单 3 所示。
清单 3. 将两个列表组合起来
<xsd:simpleType name="MaritalStatusType_Union">
<xsd:union memberTypes="MyExtMaritalStatusEnumType MaritalStatusEnumType"/>
</xsd:simpleType>
<xsd:element name="MaritalStatus" type="MaritalStatusType_Union"/>
|
该解决方案仍然需要对模式进行编辑 — 即将元素 MaritalStatus
由 MaritalStatusType
类型转换为 MaritalStatusType_Union
类型。改动不大,但仍然有一些手动编辑工作。
-
优点:不改变原始枚举列表。
-
缺点:
- 在设计阶段所有的值必须是已知的,防止后期绑定解决方案。
- 需要
<xsd:union>
标记支持,但有时该标记无法用工具实现。
解决方案 3: 创建一个模式,并与原始枚举类型结合
现在看一下有关眼睛颜色的人口数据用例。清单 4 显示这一列表。
清单 4. Person Eye Color 枚举列表
<xsd:simpleType name="PersonEyeColorType">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="Black"/>
<xsd:enumeration value="Hazel"/>
<xsd:enumeration value="Gray"/>
<xsd:enumeration value="Brown"/>
<xsd:enumeration value="Violet"/>
<xsd:enumeration value="Green"/>
<xsd:enumeration value="Blue"/>
<xsd:enumeration value="Maroon"/>
<xsd:enumeration value="Pink"/>
<xsd:enumeration value="Dichromatic"/>
<xsd:enumeration value="Unknown"/>
</xsd:restriction>
</xsd:simpleType>
|
接下来,创建采用新值的模式(一个正则表达式)。该模式是以 x:
为前缀的任意字符串。x:
是标准枚举列表和扩展列表之间的描绘程序。清单 5 显示这一模式。
清单 5. 用于扩展的正则表达式
<xsd:simpleType name="StringPatternType">
<xsd:restriction base="xsd:string">
<xsd:pattern value="x:\S.*"/>
</xsd:restriction>
</xsd:simpleType>
|
最后,使用 <xsd:union>
标记结合列表与模式,如 清单 6 所示。
清单 6. 枚举列表与扩展模式的结合
<xsd:simpleType name="MyExtPersonEyeColorType">
<xsd:union memberTypes="PersonEyeColorType StringPatternType"/>
</xsd:simpleType>
<xsd:element name="PersonEyeColor" type="MyExtPersonEyeColorType"/>
|
同一节点拥有标准和扩展值。两个值很容易分离,而且都可以用解析器验证,如 清单 7 所示。
清单 7. XML 实例样例
<PersonEyeColor>Black</PersonEyeColor>
<PersonEyeColor>x:Teal</PersonEyeColor>
|
-
优点:
- 同一元素可用于所有数据。
- 用解析器对基本枚举列表进行验证。
- 清晰地分隔扩展值。
- 该解决方案允许在以后绑定新值。
-
缺点:
- 必须解析元素的内容,以确定是否已经被扩展。
- 模式解析器必须支持正则表达式。
- 需要
<xsd:union>
标记支持。
解决方案 4:使用单独的字段用于扩展
在该解决方案中,枚举字段不会变化。然而,您要在模式中设计一个扩展字段来容纳附加值。在本例中,初始列表是依赖型的(就业受益者和受养人之间的关系),如 清单 8 所示。
清单 8. 依赖关系枚举列表
<xsd:simpleType name="DependentRelationshipEnumType">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="AdoptedChild"/>
<xsd:enumeration value="Brother"/>
<xsd:enumeration value="Child"/>
<xsd:enumeration value="ExSpouse"/>
<xsd:enumeration value="Father"/>
<xsd:enumeration value="Granddaughter"/>
<xsd:enumeration value="Grandson"/>
<xsd:enumeration value="Grandfather"/>
<xsd:enumeration value="Grandmother"/>
<xsd:enumeration value="LifePartner"/>
<xsd:enumeration value="Mother"/>
<xsd:enumeration value="Sister"/>
<xsd:enumeration value="Spouse"/>
<xsd:enumeration value="Extension"/>
</xsd:restriction>
</xsd:simpleType>
|
需要一个能够容纳新值的附加属性 — extension
—。清单 9 显示了该属性。
清单 9. 依赖关系的 extension 属性
<xsd:complexType name="DependentRelationshipType">
<xsd:simpleContent>
<xsd:extension base="DependentRelationshipEnumType">
<xsd:attribute name="extension" type="xsd:string"/>
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>
<xsd:element name="DependentRelationship" type="DependentRelationshipType"/>
|
清单 10 显示一些反映 extension 的 XML 实例。
清单 10. 示例 XML 实例
<DependentRelationship>Child</DependentRelationship>
<DependentRelationship extension="MyNewRelationship">Extension</DependentRelationship>
|
-
优点:
- 不需要编辑原始模式。
- 该解决方案允许在以后绑定新值。
- 在原始模式中显式设计
extension
方法。
-
缺点:
- 在设计阶段,必须在每个枚举列表中设计
extension
方法。
- 必须在元素中而不是在属性中设置枚举值。
解决方案 5: 基于文档的方法 —— 与字符串结合
注意:解决方案 5 和解决方案 6 违反了在一个周期内进行验证 这一要求。但是,我之所以在这里介绍它们,是因为在很多实际环境中可以使用这些方法。
在第 5 个解决方案中,使用 <xsd:union>
标记将枚举列表与字符串结合。实际上,该解决方案提示接收系统哪些值是标准的(包括包装和拼写)。但实际上字符串字段可以存放任何值。因此,解析器并不验证值。相反,这些值在第二个周期或者在接收数据的应用程序中验证。有些 XML 组织就使用这样的方案。
清单 11 显示通过 <xsd:union>
将一个枚举列表和 <xsd:string>
结合。因为任意值都可以是一个字符串,所以不用验证枚举列表。这些值建议使用标准值。
清单 11. 与字符串结合的 DayOfWeek 枚举列表
<xsd:simpleType name="DayOfWeekEnumType">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="Sunday"/>
<xsd:enumeration value="Monday"/>
<xsd:enumeration value="Tuesday"/>
<xsd:enumeration value="Wednesday"/>
<xsd:enumeration value="Thursday"/>
<xsd:enumeration value="Friday"/>
<xsd:enumeration value="Saturday"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:element name="DayOfWeek" type="DayOfWeekEnumType"/>
<xsd:simpleType name="ExtendedDayOfWeekType">
<xsd:union memberTypes="DayOfWeekEnumType xsd:string"/>
</xsd:simpleType>
<xsd:element name="DayOfWeek_solution5" type="ExtendedDayOfWeekType"/>
|
-
优点:可以添加任意的扩展值,即使在后期绑定时也可以添加。
-
缺点:
- 解析器不验证枚举值,在第二个步骤中才进行验证。
- 需要
<xsd:union>
标记支持。
解决方案 6: 基于文档的方法 —— 使用 <xsd:annotation>
要使用该方法,将实际的枚举值放到 <xsd:documentation>
标记内,同时将数据字段保留为一个简单字符串。清单 12 显示枚举值。
清单 12. 在 <xsd:documentation> 标记内的枚举值
<xsd:element name="DayOfWeek" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
<!-- suggested enumerations -->
<xsd:enumeration value="Sunday"/>
<xsd:enumeration value="Monday"/>
<xsd:enumeration value="Tuesday"/>
<xsd:enumeration value="Wednesday"/>
<xsd:enumeration value="Thursday"/>
<xsd:enumeration value="Friday"/>
<xsd:enumeration value="Saturday"/>
</xsd:documentation>
</xsd:annotation>
</xsd:element>
|
-
优点:
- 可以添加任意的扩展值,即使在后期绑定时也可以添加。
- 只需要最简单的 XML 模式特性。
-
缺点:解析器不验证枚举值。
未讨论的方法
我省略了其他几种扩展枚举列表的解决方案。下面简单介绍了两种没有使用的方法:
-
使用
<xsd:redefine>
标记: 通常不使用 XML 模式的这一特性,而且一般无法用工具实现它。该方法经常被认为是避免重新定义的最佳实践。
-
使用
substitutionGroup
元素替换包含所有值的联合列表: 另外一种出色的解决方案,使用了替换组和联合。将原始列表与新列表联合以创建一个完整的枚举列表,然后使用 substitutionGroups
标记(或 <xsi:type>
标记)替换一个全局作用域元素。该方法的缺点是替换不能派生有效的联合,替换需要两个组件来自相同的基类型。扩展和限制是替换的两个有效方法。但是,根据 XML 模式规范,联合并不是有效的派生技术(参阅 参考资料)。
结束语
XML 模式设计者和实现人员需要一种方法来扩展现有的枚举列表。因为一旦原始列表创建后,规范不允许进行扩展,因此需要找到一种方法实际实现扩展。实现人员可以使用本文的示例来设计和扩展枚举列表。每种方法都有优缺点,没有一种方法在所有用例中都是最佳方法。那么,应该使用哪种方法呢?
请考虑这些经验法则:
- 如果您习惯编辑原始枚举列表或模式,而且在设计阶段就知道所有要扩展的枚举值,最好使用 解决方案 1(手动编辑原始列表)或 解决方案 2(创建新列表并加入到原始列表中)。
- 如果想使用相同的语义元素来包含基本枚举列表和扩展枚举列表,可以考虑 解决方案 3(与模式联合)。
- 如果允许原始列表与扩展列表有不同的字段,可以使用 解决方案 4(独立的字段)。
- 如果不想在解析器中解析枚举值,可以考虑 Genericode 方法或使用 解决方案 5 或 解决方案 6。
这些指导原则可以使模式设计者找到实用的最佳实践,而且可以帮助他们创建易于实现、可扩展的枚举列表。
下载
描述
名字
大小
下载方法
XML 模式和 XML 实例示例
ExtendEnumeratedListsCode.zip |
2KB |
HTTP |
分享到:
相关推荐
在XML模式设计中,扩展枚举列表是一个常见的需求,特别是在系统需要适应未来可能出现的新值时。由于XML模式规范自身并不支持直接在枚举列表中进行扩展,设计者必须寻找替代策略来实现这一功能。本文主要探讨了几种...
数据库设计素材在 XML 模式中扩展枚举列表
总结来说,XML Schema提供了一种强大且灵活的方式,用于定义和验证XML文档的结构和内容,其丰富的特性使其在XML应用中占据重要地位。通过学习和熟练掌握XML Schema,开发者能够更好地控制和管理XML文档的规范性,...
在转换过程中,可以通过`XmlWriteMode`和`XmlReadMode`枚举控制XML生成和解析的行为。例如,你可以选择是否忽略空值、是否写入架构信息等。 6. `DataSet`与XML的数据关系: 当`DataSet`包含数据关系(如主键-外键...
通过本次实验,学生将能够深入理解XML Schema的基本概念及其在实际应用中的重要性。不仅可以学习到如何定义和验证XML文档的结构和类型,还能够提升解决问题的能力,为进一步的学习和研究打下坚实的基础。同时,实验...
本章节重点介绍XML命名空间和XML模式的概念与应用,这两种工具在解决XML文档中元素重复定义、提高数据描述准确性等方面发挥着重要作用。 #### 一、命名空间(Namespace) **概念解释** 命名空间是一种用于解决XML...
首先,XML Schema 通过使用`.xsd`扩展名的文件来定义XML文档的结构。这些模式文件可以定义XML元素、属性、数据类型以及它们之间的关系。例如,`<xsd:element>`标签用于声明一个元素,而`<xsd:complexType>`则用于...
在Spring Boot和MyBatis的集成应用中,我们经常需要处理枚举类型的数据。枚举在编程中是一种常用于表示固定数量和含义的值的类型,...在实际项目中,可以将这个模式抽象成一个通用的枚举处理工具,以便在多个地方复用。
XML Schema是XML(可扩展标记语言)文档结构和数据类型的一种规范,用于增强XML文档的结构化和验证能力。W3C School提供的XML Schema中文教程是学习这一规范的重要资源,旨在帮助用户理解并掌握XML Schema的基本概念...
- `LoadOptions`是一个枚举类型,定义了在加载XML时应采用的不同选项。例如: - `None`:默认值,不指定任何特殊加载行为。 - `SetLineInfo`:指示读取器记录行号信息,这有助于调试时确定错误发生的位置。 - `...
在WEB编程技术中,CSS(层叠样式表)、DTD(文档类型定义)、XSD(XML架构定义)和XML(可扩展标记语言)是至关重要的组成部分。这些技术共同为创建高效、结构化的网页提供了坚实的基础。 首先,CSS是用于描述HTML...
8. **第二章 Schema**:这个文件名可能指的是学习XML Schema的一个章节,该章节可能详细讲解了Schema的某一部分,如数据类型的扩展、限制、枚举值、模式匹配等。 总之,XML基础实例和Schema是XML编程中的核心概念。...
Scheme是另一种XML模式语言,比DTD提供了更强大的数据类型和约束能力。它允许更复杂的结构定义,如枚举类型、列表、选择等。 总结,XML学习涵盖了从基础概念到实际应用的方方面面,理解并掌握XML可以帮助开发者更好...
Java中没有内置的访问者模式,但在自定义的XML解析库中常被使用。 18. **备忘录模式**:在不破坏封装性的前提下,捕获一个对象的状态,以便以后恢复。Java中的`Serializable`接口可以实现对象的序列化,实现数据...
XML Schema技术是XML(可扩展标记语言)标准的一部分,它为XML文档定义了一种结构化模式,用于规范XML文档的结构和数据类型。XML Schema替代了早期的DTD(文档类型定义),提供了更强大的功能和更复杂的验证机制。...
在Java中,可以通过双重检查锁定(Double-Checked Locking)或枚举方式实现单例,避免多线程环境下的并发问题。 2. 工厂模式:提供创建对象的接口,但不直接实例化对象,而是让子类决定实例化哪个类。工厂方法模式...
在Java中,可以使用枚举、双重检查锁定或静态内部类来实现单例,以保证线程安全和防止反序列化创建新实例。 2. **工厂模式(Factory)** 工厂模式提供了一个创建对象的接口,但让子类决定实例化哪一个类。它封装了...
XML(eXtensible Markup Language)是一种用于存储和传输数据的标记语言,它以其结构化、可扩展性和易于解析的特点广泛应用于软件开发中。在这个主题中,我们将深入探讨"XML文件读取快捷类",这是一个方便程序员快速...
标题 "使用模式设计及java5新特性在HibernateDAO中的应用" 涉及到的是软件开发中的两个关键领域:设计模式和Java编程语言的新特性,特别是在数据访问对象(DAO)层如何结合使用它们。这篇文章可能详细阐述了如何利用...