XSD Substitution

Replace elements with alternative elements in XML Schema

🔄 What is XSD Substitution?

XSD substitution allows you to replace one element with another compatible element in your XML documents. This provides flexibility when different elements can serve the same purpose in your schema.


<!-- Substitution Group Example -->
<xs:element name="vehicle" type="xs:string"/>
<xs:element name="car" substitutionGroup="vehicle"/>
                                    

Key Substitution Concepts

🎯

Head Element

The main element that can be substituted

<xs:element name="payment"/>
🔀

Substitute Elements

Alternative elements that replace the head

<xs:element name="creditCard" 
  substitutionGroup="payment"/>
✅

Type Compatibility

Substitutes must match or extend the type

<xs:complexType>
  <xs:extension base="paymentType"/>
</xs:complexType>
🔒

Block Substitution

Prevent unwanted element substitution

<xs:element name="item" 
  block="substitution"/>

🔹 Basic Substitution Example

Create a substitution group where different vehicle types can replace the main vehicle element. This allows flexibility in your XML documents while maintaining schema validation.

<!-- XSD Schema -->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  
  <!-- Head element -->
  <xs:element name="vehicle" type="xs:string"/>
  
  <!-- Substitute elements -->
  <xs:element name="car" substitutionGroup="vehicle"/>
  <xs:element name="bike" substitutionGroup="vehicle"/>
  <xs:element name="truck" substitutionGroup="vehicle"/>
  
</xs:schema>

<!-- Valid XML using substitution -->
<car>Toyota</car>
<bike>Honda</bike>
<truck>Ford</truck>

Result:

✅ All three elements are valid substitutes for "vehicle"

✅ Schema validation passes for each element

🔹 Complex Type Substitution

Use substitution with complex types to create more sophisticated element hierarchies. Substitute elements can extend the base type with additional properties.

<!-- XSD Schema with Complex Types -->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  
  <!-- Base type -->
  <xs:complexType name="PaymentType">
    <xs:sequence>
      <xs:element name="amount" type="xs:decimal"/>
    </xs:sequence>
  </xs:complexType>
  
  <!-- Head element -->
  <xs:element name="payment" type="PaymentType"/>
  
  <!-- Extended type for credit card -->
  <xs:complexType name="CreditCardType">
    <xs:complexContent>
      <xs:extension base="PaymentType">
        <xs:sequence>
          <xs:element name="cardNumber" type="xs:string"/>
        </xs:sequence>
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>
  
  <!-- Substitute element -->
  <xs:element name="creditCard" type="CreditCardType" 
              substitutionGroup="payment"/>
  
</xs:schema>

<!-- Valid XML -->
<creditCard>
  <amount>99.99</amount>
  <cardNumber>1234-5678-9012-3456</cardNumber>
</creditCard>

Result:

✅ creditCard extends PaymentType with additional fields

✅ Can be used anywhere "payment" is expected

🔹 Blocking Substitution

Control which elements can be substituted using the block attribute. This prevents unwanted substitutions and maintains stricter schema control when needed.

<!-- Prevent substitution -->
<xs:element name="product" type="xs:string" block="substitution"/>

<!-- This will NOT be allowed -->
<xs:element name="book" substitutionGroup="product"/>

<!-- Allow only extension, not restriction -->
<xs:element name="item" block="restriction"/>

Block Values:

  • substitution: Prevents all substitution
  • extension: Blocks extended types
  • restriction: Blocks restricted types
  • #all: Blocks everything

🔹 Practical Use Case

Real-world example of substitution in an order system where different product types can be ordered:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  
  <!-- Base product element -->
  <xs:element name="product">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="name" type="xs:string"/>
        <xs:element name="price" type="xs:decimal"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  
  <!-- Specific product types -->
  <xs:element name="book" substitutionGroup="product"/>
  <xs:element name="electronics" substitutionGroup="product"/>
  <xs:element name="clothing" substitutionGroup="product"/>
  
</xs:schema>

<!-- Order XML -->
<order>
  <book>
    <name>XML Guide</name>
    <price>29.99</price>
  </book>
  <electronics>
    <name>Laptop</name>
    <price>899.99</price>
  </electronics>
</order>

🧠 Test Your Knowledge

What attribute is used to define a substitution group?