Procedure for Calling a Generated C Encode Function

The encode function generated for an XSD global element definition is the normal entry point for encoding an XML document. The general procedure for calling a global element encode function is as follows:

  1. Prepare a context variable for encoding

  2. Initialize an encode message buffer or stream to receive the encoded XML data

  3. Populate the data variable with data to be encoded

  4. Call the appropriate compiler-generated encode function to encode the message

  5. If a message buffer was used, get the start pointer and length of the encoded message

Before a C XML encode function can be called; the user must initialize a context variable. This is a variable of type OSCTXT. This variable holds all of the working data used during the encoding of a message. The context variable is declared as a normal automatic variable within the top-level calling function. It must be initialized before use. This can be accomplished by using the rtXmlInitContext function:

       OSCTXT ctxt;/* context variable */
          if (rtXmlInitContext (&ctxt) != 0) {
              /* initialization failed, could be a license problem */
              printf ("context initialization failed (check license)\n");
              return -1;
       }       

The next step is to specify an encode buffer or stream into which the message will be encoded. This is accomplished by calling the rtXmlSetEncBufPtr run-time function (for a message buffer) or one of the rtxStream functions to create an output stream. If a message buffer is to be used, the user has the option to either pass the address of a buffer and size allocated in his or her program (referred to as a static buffer), or set these parameters to zero and let the encode function manage the buffer memory allocation (referred to as a dynamic buffer). Better performance can normally be attained by using a static buffer because this eliminates the high-overhead operation of allocating and reallocating memory.

XBinder currently supports encoding in UTF-8, UTF-16 and ISO-8859-1. By default, the enocded XML message is in UTF-8 encoding. To encode the XML message in UTF-16 or ISO-8859-1 encoding, use the rtXmlSetEncodingStr run-time function. For example:

       rtXmlSetEncodingStr (&ctxt, (OSUTF8CHAR*)"UTF-16LE");
            

After initializing the context and populating a variable of the structure to be encoded, an encode function can be called to encode the message. If the return status indicates success, the run-time library function rtXmlGetEncBufPtr can be called to obtain the start address of the encoded message. In the static case, this is simply the start address of the static buffer. In the dynamic case, this function will return the pointer to the allocated memory buffer. The memory allocated for a dynamic buffer will be freed when either the context is freed ( rtxFreeContext ) or all memory associated with the context is released ( rtxMemFree ) or the buffer memory is explicity released ( rtxMemFreePtr ).

In the stream case, the pointer to the encoded message generally cannot be obtained since the message has already been written to the stream. The only thing necessary to do in this case is to close the stream after encoding is complete. Use the rtxStreamClose function which should be called before the rtxFreeContext function.

A program fragment that could be used to encode an employee record is as follows:

   #include "employee.h"

   #define MAXMSGLEN 1024

   int main (int argc, char** argv)
   {
      PersonnelRecord employee;
      OSCTXT ctxt;
      OSOCTET msgbuf[MAXMSGLEN];
      int i, stat;
      const char* filename = "message.xml";

      /* Init context */

      stat = rtXmlInitContext (&ctxt);
      if (0 != stat) {
         printf ("Context initialization failed.\n");
         rtxErrPrint (&ctxt);
         return stat;
      }

      /* Populate structure of generated type */

      Init_PersonnelRecord (&ctxt, &employee);

      ... logic to populate structure here ...

      /* Encode */

      stat = rtXmlSetEncBufPtr (&ctxt, msgbuf, sizeof(msgbuf));

      if (0 == stat)
         stat = XmlE_personnelRecord (&ctxt, &employee);

      if (0 == stat) {
         printf ("encoded XML message:\n");
         printf (msgbuf);
         printf ("\n");
      }
      else {
         printf ("Encoding failed\n");
         rtxErrPrint (&ctxt);
         return stat;
      }

         ... logic to process encoded message (write to file, etc.) ...
   
      rtxFreeContext (&ctxt);

This example used a static message buffer. The encoded XML text will reside in the msgbuf message buffer when the procedure complete.

A program fragment that could be used to encode an employee record to a file stream is as follows:

    #include "rtxsrc/rtxStreamFile.h"
    #include "employee.h"

    int main (int argc, char** argv)
    {
       PersonnelRecord employee;
       OSCTXT ctxt;
       int stat;
       const char* filename = "message.xml";

       /* Init context */

       stat = rtXmlInitContext (&ctxt);
       if (0 != stat) {
          printf ("Context initialization failed.\n");
          rtxErrPrint (&ctxt);
          return stat;
       }

       /* Populate structure of generated type */

       Init_PersonnelRecord (&ctxt, &employee);

       ... logic to populate structure here ...

       /* Encode directly to output stream */

       stat = rtxStreamFileCreateWriter (&ctxt, filename);
       if (0 != stat) {
          printf ("Stream initialization failed.\n");
          rtxErrPrint (&ctxt);
          return stat;
       }

       stat = XmlE_personnelRecord (&ctxt, &employee);

       if (0 != stat) {
          printf ("Encoding failed\n");
          rtxErrPrint (&ctxt);
          return stat;
       }
       rtxStreamClose (&ctxt);
       rtxFreeContext (&ctxt);
       return 0;
    }