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.