A substitution group is a feature of XML schema that allows you to specify elements that can replace another element in documents generated from that schema. The replaceable element is called the head element and must be defined in the schema’s global scope. The elements of the substitution group must be of the same type as the head element or a type that is derived from the head element’s type.
In essence, a substitution group allows you to build a collection of elements that can be specified using a generic element. For example, if you are building an ordering system for a company that sells three types of widgets you might define a generic widget element that contains a set of common data for all three widget types. Then you can define a substitution group that contains a more specific set of data for each type of widget. In your contract you can then specify the generic widget element as a message part instead of defining a specific ordering operation for each type of widget. When the actual message is built, the message can contain any of the elements of the substitution group.
Substitution groups are defined using the substitutionGroup
attribute of the XML Schema
element
element. The value of the substitutionGroup
attribute is
the name of the element that the element being defined replaces. For example, if your head element is
widget
, adding the attribute substitutionGroup="widget" to an
element named woodWidget
specifies that anywhere a widget
element is used, you can substitute a woodWidget
element. This is shown in
Example 15.1.
Example 15.1. Using a Substitution Group
<element name="widget" type="xsd:string" />
<element name="woodWidget" type="xsd:string"
substitutionGroup="widget" />
The elements of a substitution group must be of the same type as the head element or of a type derived from the head element’s type. For example, if the head element is of type xsd:int all members of the substitution group must be of type xsd:int or of a type derived from xsd:int. You can also define a substitution group similar to the one shown in Example 15.2 where the elements of the substitution group are of types derived from the head element’s type.
Example 15.2. Substitution Group with Complex Types
<complexType name="widgetType"> <sequence> <element name="shape" type="xsd:string" /> <element name="color" type="xsd:string" /> </sequence> </complexType> <complexType name="woodWidgetType"> <complexContent> <extension base="widgetType"> <sequence> <element name="woodType" type="xsd:string" /> </sequence> </extension> </complexContent> </complexType> <complexType name="plasticWidgetType"> <complexContent> <extension base="widgetType"> <sequence> <element name="moldProcess" type="xsd:string" /> </sequence> </extension> </complexContent> </complexType> <element name="widget" type="widgetType" /> <element name="woodWidget" type="woodWidgetType" substitutionGroup="widget" /> <element name="plasticWidget" type="plasticWidgetType" substitutionGroup="widget" /> <complexType name="partType"> <sequence> <element ref="widget" /> </sequence> </complexType> <element name="part" type="partType" />
The head element of the substitution group, widget
, is defined as being of type
widgetType. Each element of the substitution group extends widgetType to include data that is
specific to ordering that type of widget.
Based on the schema in Example 15.2, the part
elements in Example 15.3 are valid.
Example 15.3. XML Document using a Substitution Group
<part> <widget> <shape>round</shape> <color>blue</color> </widget> </part> <part> <plasticWidget> <shape>round</shape> <color>blue</color> <moldProcess>sandCast</moldProcess> </plasticWidget> </part> <part> <woodWidget> <shape>round</shape> <color>blue</color> <woodType>elm</woodType> </woodWidget> </part>
You can define an abstract head element that can never appear in a document produced using your schema. Abstract head elements are similar to abstract classes in Java because they are used as the basis for defining more specific implementations of a generic class. Abstract heads also prevent the use of the generic element in the final product.
You declare an abstract head element by setting the abstract
attribute of an
element
element to true
, as shown in
Example 15.4. Using this schema, a valid review
element can
contain either a positiveComment
element or a negativeComment
element, but cannot contain a comment
element.
Example 15.4. Abstract Head Definition
<element name="comment" type="xsd:string" abstract="true" />
<element name="positiveComment" type="xsd:string"
substitutionGroup="comment" />
<element name="negtiveComment" type="xsd:string"
substitutionGroup="comment" />
<element name="review">
<complexContent>
<all>
<element name="custName" type="xsd:string" />
<element name="impression" ref="comment" />
</all>
</complexContent>
</element>