XML Attribute Declarations

XML attribute declarations in XSD are translated into ASN.1 elements that are added to a SEQUENCE type. In binary encodings, there is no way to tell encoded attributes apart from encoded elements. They just represent data fields in ASN.1. For XML, special logic is added to the generated XML encoders and decoders to encode and decode the items as attributes.

An example of an attribute being added to an xsd:sequence declaration is as follows:

   <xsd:complexType name="Name">
      <xsd:sequence>
         <xsd:element name="givenName" type="xsd:string "/>
         <xsd:element name="initial" type="xsd:string"/>
         <xsd:element name="familyName" type="xsd:string"/>
      </xsd:sequence>
      <xsd:attribute name ="occupation" type="xsd:string"/>
   </xsd:complexType>

This results in the following C type definition being generated:

   typedef struct EXTERN Name {
      struct {
         unsigned occupationPresent : 1;
      } m;
      const OSUTF8CHAR* occupation;
      const OSUTF8CHAR* givenName;
      const OSUTF8CHAR* initial;
      const OSUTF8CHAR* familyName;
   } Name;

The attribute is marked as optional (hence the occupationPresent flag in the bit mask) since XML attributes are optional by default. The attribute declarations also occur before the element declarations in the generated structure.

Attributes can also be added to a choice group. In this case, an ASN.1 SEQUENCE is formed consisting of the attribute elements and an embedded element, choice, for the choice group. An example of this is as follows:

   <xsd:complexType name="NamePart">
      <xsd:choice>
         <xsd:element name="givenName" type="xsd:string "/>
         <xsd:element name="initial" type="xsd:string"/>
         <xsd:element name="familyName" type="xsd:string"/>
      </xsd:choice>
      <xsd:attribute name ="occupation" type="xsd:string"/>
   </xsd:complexType>

This results in the following C type definitions being generated:

   #define T_NamePart_choice_givenName        1
   #define T_NamePart_choice_initial          2
   #define T_NamePart_choice_familyName       3

   typedef struct EXTERN NamePart_choice {
      int t;
      union {
         /* t = 1 */
         const OSUTF8CHAR* givenName;
         /* t = 2 */
         const OSUTF8CHAR* initial;
         /* t = 3 */
        const OSUTF8CHAR* familyName;
      } u;
   } NamePart_choice;

   typedef struct EXTERN NamePart {
      struct {
         unsigned occupationPresent : 1;
      } m;
      const OSUTF8CHAR* occupation;
      NamePart_choice choice;
   } NamePart;

In this case, occupation attribute declaration was added as before. But the choice group became a separate embedded element called choice which the ASN1C compiler pulled out to create the NamePart_choice temporary type. This type was then referenced by the choice element in the generated type definition for NamePart.