spring xml 枚举_扩展XML模式中的枚举列表

spring xml 枚举

模式设计者和实现者需要一种方法来扩展XML模式中的现有枚举列表。 不幸的是,XML Schema规范不允许在创建这些列表时进行扩展(请参阅参考资料 )。 在设计时选择的值是固定的,并且全部可用。 尽管有此限制,人们还是使用各种变通办法来启用列表扩展。 我的客户经常要求使用此功能,其中许多客户都使用无法更改的现有架构。 他们希望添加新功能,同时保持向后兼容性。 在本文中,您将看到架构设计师如何克服障碍来启用此功能。

枚举列表是针对特定数据点的一组指定值。 例如,您可能将国家/地区代码视为固定的值列表,包括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相同目的使用现有元素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_Union代替MaritalStatusType 。 减少了干扰,但仍需进行一些手工编辑。

  • 优点:原始枚举列表未触及。
  • 缺点:
    • 在设计时必须知道所有值,以防止后期绑定解决方案。
    • 需要<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. Dependency Relationship扩展属性
<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显示了一些反映扩展的XML实例。

清单10.示例XML实例
<DependentRelationship>Child</DependentRelationship>
<DependentRelationship extension="MyNewRelationship">Extension</DependentRelationship>
  • 优点:
    • 无需编辑原始架构。
    • 该解决方案可以适应新值的后期绑定。
    • extension方法被明确地设计到原始模式中。
  • 缺点:
    • 必须在设计时将extension方法设计到每个枚举列表中。
    • 枚举值必须出现在元素中,而不是属性中。

解决方案5:基于文档的方法-与字符串结合

注意:解决方案5和6一口气违反了验证要求。 但是,我将它们包括在这里是因为它们是许多实际环境中使用的方法。

在第五种解决方案中,您将使用一个枚举列表,该列表使用<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 Schema规范,并集不是有效的派生技术(请参阅参考资料 )。

结论

XML模式设计者和实现者需要一种扩展现有枚举列表的方法。 由于一旦创建了原始列表,规范就不允许这样做了,因此一种解决方法对于使现实世界的实现成为可能至关重要。 实现者可以使用本文中的示例来帮助设计和扩展枚举。 每种方法都有优点和缺点,但在所有情况下都不是最佳实践。 那么,您应该使用哪种方法?

考虑以下经验法则:

  • 如果您对编辑原始枚举列表或架构感到满意,并且在设计时知道所有扩展的枚举值,则解决方案1 (手动编辑原始列表)或解决方案2 (创建新列表并将其加入到原始列表)可能是最好的选择。
  • 如果要使用相同的语义元素同时包含基本枚举和扩展枚举,请考虑解决方案3 (带模式的联合)。
  • 如果您不介意列表和扩展名使用不同的字段,则解决方案4 (单独的字段)将起作用。
  • 如果要将枚举值保留在解析器之外,请考虑使用Genericode方法,或使用解决方案5解决方案6

这些准则可以使架构设计人员具有实际可行的最佳实践,并可以帮助创建易于实现的可扩展枚举列表。


翻译自: https://www.ibm.com/developerworks/xml/library/x-extenum/index.html

spring xml 枚举

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值