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
.