A substitution group is similar to a complex content type in that it allows derivations from a common base. In this case, however, the base is an XSD element and the substitution group allows any of a set of elements defined to be in the group to be used in the place of the base element. A simple example of this is as follows:
<xsd:element name="MyElement" type="MyType"/> <xsd:complexType name="MyType"> <xsd:sequence> <xsd:element ref="MyBaseElement"/> </xsd:sequence> </xsd:complexType> <xsd:element name="MyBaseElement" type="xsd:string"/> <xsd:element name="MyExtendedElement" type="xsd:string" substitutionGroup="MyBaseElement "/>
In this case, the global element MyElement
references
MyType
which is defined as a sequence with a single element reference to
MyBaseElement
. MyBaseElement
is the head element in a
substitution group that also includes MyExtendedElement
. This means
MyType
can either reference MyBaseElement
or
MyExtendedElement
.
As per X.694, ASN1C generates a special type that acts as a container for all the
different possible elements in the substitution group. This is a choice type with the
name <BaseElement>_group
where <BaseElement>
would be
replaced with the name of the subsitution group head element (MyBaseElement
in this case).
The generated C type definitions for the above XSD definitions follow:
typedef const OSUTF8CHAR* MyBaseElement; typedef const OSUTF8CHAR* MyExtendedElement; #define T_MyBaseElement_group_myBaseElement 1 #define T_MyBaseElement_group_myExtendedElement 2 typedef struct EXTERN MyBaseElement_group { int t; union { /* t = 1 */ MyBaseElement myBaseElement; /* t = 2 */ MyExtendedElement myExtendedElement; } u; } MyBaseElement_group; typedef struct EXTERN MyType { MyBaseElement_group myBaseElement; } MyType; typedef MyType MyElement;
In this case, if MyElement
or MyType
is used, it can be
populated with either base element or extended element data.