CHOICE

The XSD CHOICE type <xsd:choice> is a complex type consisting of a series of element definitions from which one may be selected to include in a message instance. It is converted into a C or C++ structured type containing an integer for the choice tag value (t) followed by a union (u) of all of the equivalent types that make up the CHOICE elements.

The tag value is simply a sequential number starting at one for each alternative in the CHOICE. For C, a #define constant is generated for each of these values. The format of this constant is T_TypeName_elemName where TypeName is the name of the XSD complexType and elemName is the name of the CHOICE alternative. For C++, an enumerated type is added to the class with enumerations of the form T_elemName.

The union of choice alternatives is made of the equivalent C or C++ type definition followed by the element name for each of the elements. The rules for element generation are essentially the same as was described for SEQUENCE above. Constructed types or elements that map to C structured types are pulled out and temporary types are created. Names for elements that are not named (e.g., for an inline content group) are automatically generated when needed.

The general mapping is as follows:

XSD type:

   <xsd:complexType name="TypeName">
      <xsd:choice>
         <xsd:element name="elem1" type="Type1"/>
         <xsd:element name="elem2" type="Type2"/>
         ...
         <xsd:element name="elemN" type="TypeN"/>
      </xsd:choice>
   </xsd:complexType>

Generated C code:

   /* choice tag constants */
   #define T_TypeName_elem1 1
   #define T_TypeName_elem2 2
   ...
   #define T_TypeName_elemN N

   typedef struct TypeName {
      OSUINT16 t;
      union {
         /* t = 1 */
         Type1 elem1;
         /* t = 2 */
         Type2 elem2;
         ...
         /* t = N */
         TypeN elemN;
      } u;
   } TypeName;

Generated C++ code:

   class TypeName : public OSXSDComplexType {
   public:
      enum {
         T_elem1 1
         T_elem2 2
         ...
         T_elemN N
      };
      OSUINT16 t;
      union {
         /* t = 1 */
         Type1 elem1;
         /* t = 2 */
         Type2 elem2;
         ...
         /* t = N */
         TypeN elemN;
      } u;
      ...
   } ;

In most cases, the generated elements within the C++ union construct will be pointers to dynamic variables rather than inline static value references.[1]One exception to this rule is if the referenced type of the element is a simple, atomic type such as an integer. The reason for using pointers is to keep the size of the structures small (otherwise, it will be sized to fit the largest possible variable size even if that alternative is not being used) and to avoid problems with C++ constructor invocations if C++ types with constructors are referenced within the union.

A second exception is for nillable elements of simple type. In that case, a pointer type is used so that a null pointer can be used to represent a nilled element. See the discussion of nillable elements under the section on sequences above.

It is possible to nest XSD sequence or choice content model groups within a choice model group. The rules for handling this are as described in the handling of nested types for sequence above.



[1] For C, inline static value references are used. This is for historical reasons.