How to Use xs:union to Validate Multiple XML Types
The xs:union simple type in XML Schema (XSD) provides a
mechanism to validate an element or attribute against a set of multiple
distinct simple types. Instead of restricting a value to a single data
type, xs:union merges the value spaces of multiple simple
types into one unified type. This article explains the mechanics of
xs:union, how the XML Schema processor validates data
against it, and how to implement it in your schema designs.
What is xs:union?
In standard XSD design, an element or attribute is typically assigned
a single simple type, such as xs:integer or
xs:date. However, real-world data often requires
flexibility, such as accepting an integer or a string like
"N/A".
The <xs:union> element enables this flexibility by
creating a new simple type that is the logical union of two or more
member types. If a document value is valid according to at
least one of these member types, the element passes validation.
How Validation Works
When an XML processor encounters an element defined by an
xs:union, it follows a specific validation process:
- Member Type Evaluation: The validator tests the lexical representation of the target value against the member types in the order they are declared.
- First Match Resolution: If the value satisfies the rules, facets, and constraints of any member type, the validation succeeds.
- Type Assignment: The value is mapped to the first member type that validates it successfully.
- Validation Failure: If the value fails to match any of the member types defined in the union, the processor throws a schema validation error.
Defining xs:union in XML Schema
You can define member types within an xs:union in two
ways: using the memberTypes attribute to reference
predefined types, or embedding anonymous simple types directly within
the <xs:union> element.
Example: Using Predefined Member Types
<xs:simpleType name="SizeCodeType">
<xs:restriction base="xs:string">
<xs:enumeration value="S"/>
<xs:enumeration value="M"/>
<xs:enumeration value="L"/>
<xs:enumeration value="XL"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="SizeNumberType">
<xs:restriction base="xs:positiveInteger">
<xs:maxInclusive value="50"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="ClothingSizeType">
<xs:union memberTypes="SizeCodeType SizeNumberType"/>
</xs:simpleType>In this example, an element using ClothingSizeType is
valid if it contains either a standard size code ("S",
"M", etc.) or a numeric size value (1 through
50).
Example: Combining Built-in and Anonymous Types
<xs:simpleType name="ZIPOrUnknownType">
<xs:union memberTypes="xs:integer">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="UNKNOWN"/>
<xs:enumeration value="PENDING"/>
</xs:restriction>
</xs:simpleType>
</xs:union>
</xs:simpleType>In this definition, the value can either be a standard integer (such
as 90210) or one of the literal string values:
"UNKNOWN" or "PENDING".
Key Considerations
- Order of Member Types: Order matters when types
overlap (for instance,
xs:integerandxs:string). The validator attempts validation in the order listed, which can affect the post-schema-validation infoset (PSVI) type assignment. - Simple Types Only:
xs:unioncan only combine simple types. It cannot be used to combine complex types or elements with child nodes. - Facet Restrictions: You can further restrict a
union by wrapping it inside another
xs:simpleTypewith an<xs:restriction>element to apply facets likepatternorenumerationto the combined set.