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:

  1. Member Type Evaluation: The validator tests the lexical representation of the target value against the member types in the order they are declared.
  2. First Match Resolution: If the value satisfies the rules, facets, and constraints of any member type, the validation succeeds.
  3. Type Assignment: The value is mapped to the first member type that validates it successfully.
  4. 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