Home > Article > Backend Development > Detailed explanation of sample code for extending enumeration list in XML schema
Adding new values to the list is a common and necessary requirement. Pattern designers often want to build into the system architecture a way to add added value, and that added value is not known during the design phase. How can a schema designer create an extensible, easy-to-implement list of enumerated values? This article will introduce several ways to achieve this goal.
Pattern designers and implementers need an extension
Adding new values to a list is a common and necessary requirement. Pattern designers often want to build into the system architecture a way to add added value, and that added value is not known during the design phase. How can a schema designer create an extensible, easy-to-implement list of enumerated values? This article will introduce several ways to achieve this goal.
Schema designers and implementers need a way to extend the existing enumeration list in the XML schema. Unfortunately, the XML Schema specification does not allow expansion during the creation of these lists (see Related topics). The values selected during the design phase are fixed and available. Despite this limitation, people still use various alternatives to achieve list expansion. This is often requested by customers using existing schemas that cannot be changed. They want to add new features while maintaining backwards compatibility. In this article, you'll see how pattern designers overcame the obstacles to achieve this functionality.
An enumeration list is a set of specified values for a specific data point. For example, you might view country codes through a fixed list of values, including DE (Germany), US (United States), and JP (Japan). Given a given set of values, what should be done when a new country is identified, such as TL (East Timor) or BA (Bosnia and Herzegovina)? Clients using the previous namelist must change their implementation to accommodate the new values.
When using XML schema to model data, enumeration values are listed explicitly. Therefore, the list of country codes contains each enumeration value in sequence. Often new values in a list need to be identified and must be accommodated into the list, and the schema designer attempts to find a way to extend the list and, in effect, build this method into the design to allow the addition of new values that are not known at design time. added value.
Create an expandable enumeration list
When looking for a solution to this problem, we were influenced by four key criteria:
First, expand the list after the design phase. Whether it's quickly establishing a new trading partner or setting up time-critical new data fields, scaling when it counts is a real need.
Secondly, being able to validate values in the parser is critical to simplifying implementation.
Third, it is critical to complete parsing and verification in a single cycle. This avoids doing validation in a separate cycle and parser like the Genericode solution. For some setups, adding new technology requirements can be too costly or time-consuming.
Finally, the solution must be backwards compatible with the original schema. Incompatible list changes cannot be called extensions.
Some people think that enumeration lists should not be extended at all. A data modeler might think that if they want their model to include more data, extending the model, they can create a schema based on the product—in effect, creating a larger model with fewer constraints when needed. If you can control the original schema and data model, it is possible to do this, and this approach may be ideal. However, if you need to actually scale after the design phase, such an approach won't work.
Others believe that the key to extending the enumeration list is not to use XML schema validation parsers. Genericode (see Related topics) recommends validating enumeration lists at a second level, independent of the initial XML schema parser validation process. This theory is correct, and the application of this method will become more and more widespread. However, this solution is not possible if it is to be completed within one parsing cycle. In some cases, it is not possible to perform a second verification cycle.
Of course, you can create new elements in a new list. However, there is no backward compatibility with raw mode. Our goal is to implement an extensible list while maintaining backward compatibility (see Resources).
For the purposes of this article, the assumptions made here are based on my experience working with customers - namely the need to extend an existing enumeration list with added value. Also, I assume that XML schema parsing and validation are done in one step.
Necessary conditions for extending the enumeration list
This extension example has four necessary conditions:
Allows the enumeration list to be extended after the design phase.
Validate the enumeration list with the parser.
Validate the enumeration list within a cycle.
Maintain backward compatibility with original mode.
For example, a team needs to process an enumerated list of regional industry associations (or any existing list) and modify the schema components according to usage. The previous schema provided an enumerated list of MaritalStatus components and values, as shown in Listing 1.
List 1. Marital status enumeration list
<xsd:simpleType name="MaritalStatusEnumType"> <xsd:restriction base="xsd:normalizedString"> <xsd:enumeration value="porced"/> <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"/>
Suppose a company wants to use these values, and in addition, supports its important trading partners to use another value. CivilUnion is an extended value that the company recognizes is not part of the original schema. But semantically speaking, it's also okay to use an existing element — MaritalStatus —. How does the company achieve this?
Back to top
Solution 1: Edit the original schema to include the new enumeration value
Of course, editing the original schema to include the new enumeration value is the most straightforward method. Keep local copies of the schemas, and then edit the schemas to support the enumeration values used by your company.
Advantages: Easy to implement
Disadvantages:
Need to edit the original patterns, these patterns will gradually change to the point of being uncontrollable. If extending a pre-existing list, the creator (trading partner, association, etc.) may want to publish a new version of the list. You need to propagate your edits to each new version.
ManualEdit modecan cause unexpected editing errors.
If you can't (or don't want to) edit the original schema, you'll need an alternative.
Back to top
Solution 2: Create a new enumeration list and add it to the original list
The second option is to create a new enumeration list and add it to the original enumeration list. Listing 1 shows the original marital status list. Listing 2 shows the newly created enumeration list.
Listing 2. New marital status enumeration list
<xsd:simpleType name="MyExtMaritalStatusEnumType"> <xsd:restriction base="xsd:normalizedString"> <xsd:enumeration value="CivilUnion"/> </xsd:restriction> </xsd:simpleType>
Use the a8a63e71ccce8bcd0a2f59429578398f tag to combine it with the original list, as shown in Listing 3.
Listing 3. Combining two list groups
<xsd:simpleType name="MaritalStatusType_Union"> <xsd:union memberTypes="MyExtMaritalStatusEnumType MaritalStatusEnumType"/> </xsd:simpleType> <xsd:element name="MaritalStatus" type="MaritalStatusType_Union"/>
This solution still requires editing the schema — that is, the element MaritalStatus is represented by MaritalStatusType Type conversion to MaritalStatusType_Union type. Not a huge change, but still some manual editing work.
Advantages: Does not change the original enumeration list.
Disadvantages:
All values must be known during the design phase to prevent late binding solutions.
Requires a8a63e71ccce8bcd0a2f59429578398f tag support, but sometimes this tag cannot be implemented with tools.
Back to top
Solution 3: Create a schema and combine it with the original enum type
Now look at the population data use case about eye color. Listing 4 shows this list.
Listing 4. Person Eye Color enumeration list
<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>
Next, create a pattern (a regular expression) that takes the new value. The pattern is any string prefixed with x:. x: is a delineator between a standard enumeration list and an extended list. Listing 5 shows this pattern.
Listing 5. Regular expression for expansion
<xsd:simpleType name="StringPatternType"> <xsd:restriction base="xsd:string"> <xsd:pattern value="x:\S.*"/> </xsd:restriction> </xsd:simpleType>
Finally, combine the list with the pattern using the a8a63e71ccce8bcd0a2f59429578398f tag, as shown in Listing 6.
Listing 6. Combination of enumeration list and extended mode
<xsd:simpleType name="MyExtPersonEyeColorType"> <xsd:union memberTypes="PersonEyeColorType StringPatternType"/> </xsd:simpleType> <xsd:element name="PersonEyeColor" type="MyExtPersonEyeColorType"/>
The same node has standard and extended values. The two values are easily separable, and both can be verified using the parser, as shown in Listing 7.
Listing 7. Sample XML instance
<PersonEyeColor>Black</PersonEyeColor> <PersonEyeColor>x:Teal</PersonEyeColor>
Advantages:
The same element can be used for all data.
Use the parser to validate the basic enumeration list.
Clearly separate extended values.
This solution allows binding new values later.
Disadvantages:
The content of the element must be parsed to determine whether it has been expanded.
The pattern parser must support regular expressions.
Requires a8a63e71ccce8bcd0a2f59429578398f tag support.
Back to top
Solution 4: Use separate fields for expansion
In this solution, the enumeration fields will not change. However, you will need to design an extension field in the schema to accommodate the additional value. In this case, the initial list is dependent (relationship between employment beneficiary and dependent), as shown in Listing 8.
Listing 8. Dependency enumeration list
<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>
Requires an additional property — extension— that can accommodate new values. Listing 9 shows this property.
Listing 9. The extension attribute for dependencies
<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"/>
Listing 10 shows some XML examples that reflect extension.
Listing 10. Sample XML instance
<DependentRelationship>Child</DependentRelationship> <DependentRelationship extension="MyNewRelationship">Extension</DependentRelationship>
优点:
不需要编辑原始模式。
该解决方案允许在以后绑定新值。
在原始模式中显式设计 extension 方法。
缺点:
在设计阶段,必须在每个枚举列表中设计 extension 方法。
必须在元素中而不是在属性中设置枚举值。
回页首
解决方案 5: 基于文档的方法 —— 与字符串结合
注意:解决方案 5 和解决方案 6 违反了在一个周期内进行验证 这一要求。但是,我之所以在这里介绍它们,是因为在很多实际环境中可以使用这些方法。
在第 5 个解决方案中,使用 a8a63e71ccce8bcd0a2f59429578398f 标记将枚举列表与字符串结合。实际上,该解决方案提示接收系统哪些值是标准的(包括包装和拼写)。但实际上字符串字段可以存放任何值。因此,解析器并不验证值。相反,这些值在第二个周期或者在接收数据的应用程序中验证。有些 XML 组织就使用这样的方案。
清单 11 显示通过 a8a63e71ccce8bcd0a2f59429578398f 将一个枚举列表和 75eb557cfb45ea1d8dae02dc93b76dca 结合。因为任意值都可以是一个字符串,所以不用验证枚举列表。这些值建议使用标准值。
清单 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"/>
优点:可以添加任意的扩展值,即使在后期绑定时也可以添加。
缺点:
解析器不验证枚举值,在第二个步骤中才进行验证。
需要 a8a63e71ccce8bcd0a2f59429578398f 标记支持。
回页首
解决方案 6: 基于文档的方法 —— 使用 fca1af215fef1d5c1bced9a59797830f
要使用该方法,将实际的枚举值放到 21dba8562c1ffae18c64c17dc18f6cb0 标记内,同时将数据字段保留为一个简单字符串。清单 12 显示枚举值。
清单 12. 在 ae418a134aca541d60939a34685157c2 标记内的枚举值
<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 模式特性。
缺点:解析器不验证枚举值。
回页首
未讨论的方法
我省略了其他几种扩展枚举列表的解决方案。下面简单介绍了两种没有使用的方法:
使用 0f2bc009383268386b5007a40602d2a3 标记: 通常不使用 XML 模式的这一特性,而且一般无法用工具实现它。该方法经常被认为是避免重新定义的最佳实践。
使用 substitutionGroup 元素替换包含所有值的联合列表: 另外一种出色的解决方案,使用了替换组和联合。将原始列表与新列表联合以创建一个完整的枚举列表,然后使用 substitutionGroups 标记(或 44403ce233a2c37c854bc989d9695611 标记)替换一个全局作用域元素。该方法的缺点是替换不能派生有效的联合,替换需要两个组件来自相同的基类型。扩展和限制是替换的两个有效方法。但是,根据 XML 模式规范,联合并不是有效的派生技术(参阅 参考资料)。
回页首
结束语
XML 模式设计者和实现人员需要一种方法来扩展现有的枚举列表。因为一旦原始列表创建后,规范不允许进行扩展,因此需要找到一种方法实际实现扩展。实现人员可以使用本文的示例来设计和扩展枚举列表。每种方法都有优缺点,没有一种方法在所有用例中都是最佳方法。那么,应该使用哪种方法呢?
请考虑这些经验法则:
如果您习惯编辑原始枚举列表或模式,而且在设计阶段就知道所有要扩展的枚举值,最好使用 解决方案 1(手动编辑原始列表)或 解决方案 2(创建新列表并加入到原始列表中)。
如果想使用相同的语义元素来包含基本枚举列表和扩展枚举列表,可以考虑 解决方案 3(与模式联合)。
如果允许原始列表与扩展列表有不同的字段,可以使用 解决方案 4(独立的字段)。
如果不想在解析器中解析枚举值,可以考虑 Genericode 方法或使用 解决方案 5 或 解决方案 6。
这些指导原则可以使模式设计者找到实用的最佳实践,而且可以帮助他们创建易于实现、可扩展的枚举列表。
XML 模式和 XML 实例示例 ExtendEnumeratedListsCode.zip 2KB
The above is the detailed content of Detailed explanation of sample code for extending enumeration list in XML schema. For more information, please follow other related articles on the PHP Chinese website!