How It Works

Users of XML parsers are probably already quite familiar with the concepts of SAX. Significant events are defined that occur during the parsing of a message. As a parser works through a message, these events are ‘fired’ as they occur by invoking user defined callback functions. These callback functions are also known as event handler functions. A diagram illustrating this parsing process is as follows:

The events are significant actions that occur during the parsing process. The following events are defined that will be passed to the user when an ASN.1 message is parsed:

  1. StartElement – This event occurs when the parser moves into a new element. For example, if we have a SEQUENCE { a, b, c } construct (type names omitted), this event will fire when we begin parsing a, b, and c. The name of the element is passed to the event handling callback function.

  2. EndElement – This event occurs when the parser leaves a given element space. Using the example above, these would occur after the parsing of a, b, and c are complete. The name of the element is once again passed to the event handling callback function.

  3. Characters method – This method is defined to pass all of the different types of primitive values that are encountered when parsing a message. The primitive values are passed out in a stringified form.

The methods corresponding to these events are defined in Asn1NamedEventHandler interface.

The start and end element methods are invoked when an element is parsed within a constructed type. The start method is invoked as soon as the tag/length is parsed in a BER or DER message. The end method is invoked after the contents of the field are processed. The signature of these methods is as follows:

   void StartElement (string name, int index);
   void EndElement (string name, int index);

The name argument is used pass the element name. The index argument is used for SEQUENCE OF/SET OF constructs only. It is used to pass the index of the item in the array. This argument is set to –1 for all other constructs.

The Characters method is used to pass out ASN.1 primitive data. This is a departure from the C++ event handler methodology in which separate methods are defined for all of the different data types. This implementation is more closely aligned with the standard SAX implementation for XML. The reason it is done this way in C# and not C++ is because it is much easier to stringify values. Since memory management is built-in to C#, it is easy to create a string and pass it out. This is a problem in C++ because it becomes a performance issue if too many malloc’s are done and it also places a burden on the user to free the memory for the allocated strings.

The signature for the Characters method is as follows:

   void Characters (string svalue, short typeCode);

The svalue argument contains the stringified value. The format of this value is ASN.1 value notation for the value as defined in the X.680 standard. The typeCode argument contains an identifier that specifies the ASN.1 type of the value. The identifier corresponds to the universal identifier values (the ID number in the universal tags) for each of the primitive data types. The only exception to this rule is that the identifier 99 was added to represent an Open Type construct. Constants for all of the identifier values are provided in the Asn1Type class. See the C# documentation for this class for a list of the constants.