Substitution Groups

Substitution groups are very similar to choice types. They allow a given base element (refered to as the substitution group head) to be replaced with a different element. The replacement element is designated as being part of the group through the use of the XSD substitutionGroup attribute.

For example, the following element declarations declare a group in which the head element (Publication) would be replaced with either the Book element or Magazine element:

   <xsd:element name="Publication" abstract="true"
       type="PublicationType"/>

   <xsd:element name="Book" substitutionGroup="Publication"
       type="BookType"/>

   <xsd:element name="Magazine" substitutionGroup="Publication"
       type="MagazineType"/>

In these declarations, the types BookType and MagazineType must be derived from the substitution group head type (in this case, PublicationType). This now allows Book or Magazine to be used anywhere where Publication was declared to be used (in fact, the elements in this case must be Book or Magazine because Publication was declared to be abstract and therefore cannot appear in an XML instance).

XBinder generates a special type to hold each of the substitution group alternative elements. This is a C struct type containing an integer tag value (t) that identifies the substitution alternative followed by a union (u) of all of the alternative element types. This is identical to the mapping for the XSD choice type described in the previous section.

The format of the name for the special type is “_<element>SG", where <element> would be replaced with the name of the substitution group head element. In the example above, the generated type name would be “_PublicationSG".

The general mapping is as follows:

XSD type:

   <xsd:element name="ElemName" type="ElemType"/>

   <xsd:element
       name="AltName1"
       substitutionGroup="ElemName"
       type="AltType1"/>

   <xsd:element
       name="AltName2"
       substitutionGroup="ElemName"
       type="AltType2"/>

   ...

   <xsd:element
       name="AltNameN"
       substitutionGroup="ElemName"
       type="AltTypeN"/>

Generated C code:

   /* choice tag constants */
   #define T__ElemNameSG_ElemName 1
   #define T__ElemNameSG_AltName1 2
   #define T__ElemNameSG_AltName2 3
   ...
   #define T__ElemNameSG_AltNameN N+1

   typedef struct _ElemNameSG {
      OSUINT16 t;
      union {
         /* t = 1 */
         ElemType ElemName;
         /* t = 2 */
         AltType1 AltName1;
         /* t = 3 */
         AltType2 AltName2;
         ...
         /* t = N+1 */
         AltTypeN AltNameN;
      } u;
   } _ElemNameSG;

Generated C++ code:

   class _ElemNameSG : public OSRTBaseType {
   public:
      enum {
         T_ElemName 1
         T_AltName1 2
         ...
         T_AltNameN N
      };
      OSUINT16 t;
      union {
         /* t = 1 */
         ElemType ElemName;
         /* t = 2 */
         AltType1 AltName1;
         ...
         /* t = N+1 */
         AltTypeN AltNameN;
      } u;
      ...
   } ;

Notes:

  1. If the substitution group head element is abstract, then an entry will not be added to the generated type for it. This is because it cannot be used in an XML instance of the type.

  2. The choice tag constants (T_TypeName_type) are the identifiers of each of the particular values in the union. The selected value is stored in the t member variable of the generated structure. In the case of C++, the tag values are in the form of an enum construct within the class containing enumerations of the form T_type.