by Aymerick Jéhanne

WBXML Library

C library for handling WBXML content

2003

Revision History
Revision Beta 0.7.02003-03-20 
First Draft for the WBXML Library 0.7.0
Revision Beta 0.7.12003-03-21 
First Draft for the WBXML Library 0.7.1 (not packaged - still leaks explanation of WBXMLTree, WBXMLTag and WBXMLAttribute interfaces)

Table of Contents

1. Overview
1.1. Components
1.2. Supported Languages
1.3. Project
1.4. Code Documentation
2. Building and Installing
2.1. Linux
2.2. Windows
3. Using WBXML Library
3.1. File convertion Tools (xml2wbxml, wbxml2xml)
3.2. Buffer convertion Library (libwbxml2_conv)
3.3. Low level WBXML Parser and Encoder (libwbxml2)
4. Reference
4.1. libwbxml2
4.1.1. WBXML Encoder
4.1.1.1. Encoder Creation
4.1.1.2. Encoder Initialization when generating WBXML or XML
4.1.1.3. Encoder Initialization when generating WBXML
4.1.1.4. Encoder Initialization when generating XML
4.1.1.5. Encoding Functions
4.1.1.6. Example
4.1.2. WBXML Parser
4.1.2.1. Parse to WBXML Tree
4.1.2.2. Parse with User Defined Callbacks
4.1.3. WBXML Tree
4.2. libwbxml2_conv
4.2.1. XML to WBXML Convertion
4.2.1.1. Prototype
4.2.1.2. XML2WBXMLParameters Structure
4.2.1.3. Example
4.2.2. WBXML to XML Convertion
4.2.2.1. Prototype
4.2.2.2. WBXML2XMLParameters Structure
4.2.2.3. Example
4.3. Tools
4.3.1. xml2wbxml
4.3.2. wbxml2xml

List of Examples

4.1. WBXML Encoder Creation/Destruction
4.2. WBXML Encoder Use
4.3. WBXML Parser Creation/Destruction
4.4. WBXML Parser use
4.5. XML to WBXML Convertion
4.6. WBXML to XML Convertion

  • WAP Forum Specifications

    • WAP 1.0

      • WBXML 1.0 - WBXML-30-Apr-98.pdf (Tested)

      • WML 1.0 - WML-30-Apr-98.pdf (Untested)

      • WTA 1.0 - wta-30-apr-98.pdf (Untested)

    • WAP 1.1

      • WBXML 1.1 - SPEC-WBXML-19990616.pdf (Tested)

      • WML 1.1 - SPEC-WML-19990616.pdf (Untested)

      • CHANNEL 1.1 - SPEC-WTA-19990716.pdf (Untested)

    • WAP 1.2

      • WBXML 1.2 - SPEC-WBXML-19991104.pdf (Tested)

      • WML 1.2 - SPEC-WML-19991104.pdf (Untested)

      • SI 1.0 - WAP-167-ServiceInd-20010731-a.pdf (Tested)

      • SL 1.0 - WAP-168-ServiceLoad-20010731-a.pdf (Tested)

    • WAP 1.2.1

      • WBXML 1.3 - WAP-192-WBXML-20010725-a.pdf (Tested)

      • WML 1.3 - WAP-191-WML-20000219-a.pdf (Untested)

      • CO 1.0 - WAP-175-CacheOp-20010731-a.pdf (Untested)

    • WAP 2.0

      • Prov 1.0 - WAP-183-PROVCONT-20010724-a.pdf (Tested)

      • WTA WML 1.2 - WAP-266-WTA-20010908-a.pdf (Untested)

      • CHANNEL 1.2 - WAP-266-WTA-20010908-a.pdf (Untested)

  • OMA Specifications

    • EMail Notification 1.0

      • EMN 1.0 - OMA-ERELD-EMN-V1_0-20021031-C.pdf (Tested)

    • Rights Expression Language Version 1.0

      • DRMREL 1.0 - OMA-Download-DRMREL-v1_0-20020913-a.pdf (Untested)

  • Nokia / Ericsson

    • OTA Settings

      • OTA_settings_general_7_0.pdf (Tested)

  • SyncML Spécifications

    • SYNCML 1.1.1

      • syncml_represent_v111_20021002.pdf (Untested)

      • syncml_metinf_v111_20021002.pdf (Untested)

      • syncml_devinf_v111_20021002.pdf (Untested)

  • Wireless-Village Spécifications

    • WV CSP 1.1

      • WSP 1.1 - WV_CSP_WBXML_v1.1.pdf (Untested)

The WBXML Library project is hosted on SourceForge

The latests package can be downloaded: here

CVS Access: :ext:anonymous@cvs.wbxmllib.sourceforge.net:/cvsroot/wbxmllib

Browe the sources Online

You must have the Expat library installed.

This is what you must do to install the WBXML Library on Linux

  1. $ ./bootstrap

  2. $ make all

  3. $ make install

  4. $ make clean

Procedure 2.1. Linux Install

[Warning]Warning

You may have to chmod 'bootstrap' file to 755, if not already done.

To make the library verbose, use the '-DWBXML_LIB_VERBOSE' CFLAG in src/Makefile.am

The Expat binary is provided in "/win32/expat".

Just open the 'win32/libwbxml.dsw' VC++ workspace, and build:

  • libwbxml2.dll - The main library

  • libwbxml2_conv.dll - The WBXML <=> XML convertion library

  • xml2wbxml.exe - The XML to WBXML convertion tool

  • xml2wbxml.exe - The WBXML to XML convertion tool

To make the library verbose, define the 'WBXML_LIB_VERBOSE' Macro in 'src/wbxml_log.h'

There are three ways of using the WBXML Library:

  • File convertion Tools : The xml2wbxml and wbxml2xml programs.
  • Buffer convertion Library : The libwbxml2_conv library.
  • Low level WBXML Parser and Encoder : The libwbxml2 library.

This are the high level components of the WBXML Library. This tools need the libwbxml2_conv, libwbxml2 and Expat libraries.

There are two Convertion Tools:

  • xml2wbxml tool - Convert an XML File to a WBXML File.
  • wbxml2xml tool - Convert a WBXML File to an XML File.

This is the library version of the Convertion Tools. Use this library if you need to convert XML and WBXML buffers inside your own Program. This library needs to link with the libwbxml2 and Expat libraries.

There are two Convertion Functions:

  • xml2wbxml function - Convert an XML Buffer to a WBXML Buffer.
  • wbxml2xml function - Convert a WBXML Buffer to an XML Buffer.

This is the low-level WBXML Library component. It uses an intermediary WBXMLTree structure to represent a WBXML Document, and it contains a WBXML Parser and a WBXML Encoder. Use this library if you have to deal with an in-memory representation of the WBXML Document, or if you want to parse a WBXML Document into your own internal structures. This is a standalone library.

The main modules of the libwbxml2 library:

wbxml_buffers

This contains functions to manipulate generic Buffers (WBXMLBuffer). This buffers are used in the 'wbxml_elt' module to store Literal Tags and Literal Attribute Names.

wbxml_tables

This module contains all the WBXML Tables. It defines too the structures:

wbxml_elt

This module defines the WBXML Elements used in the WBXML Tree structure:

        typedef struct WBXMLTag_s {
            WBXMLValueType type;                    /* Tag Type (Token or Literal) */
            union {
                const WBXMLTagEntry   *token;       /* Token Tag (MUST be const structure, ie from wbxml_tables.c) */
                WBXMLBuffer           *literal;     /* Literal Tag (MUST be dynamically allocated WBXMLBuffer) */
            } u;
        } WBXMLTag;
                            
The WBXMLTag type can be either:
  • WBXML_VALUE_TOKEN - In this case, the Tag Name is a token, a pointer to a WBXMLTagEntry structure.
  • WBXML_VALUE_LITERAL - In this case, the Tag Name is a literal, a pointer to a WBXMLBuffer structure.

        typedef struct WBXMLAttributeName_s {
            WBXMLValueType  type;               /* Attribute Name Type (Token or Literal) */
            union {
                const WBXMLAttrEntry *token;    /* Token Attribute Name (MUST be const structure, ie from wbxml_tables.c) */
                WBXMLBuffer          *literal;  /* Literal Attribute Name (MUST be dynamically allocated WBXMLBuffer) */
            } u;
        } WBXMLAttributeName;
                            
The WBXMLAttributeName type can be either:
  • WBXML_VALUE_TOKEN - In this case, the Attribute Name is a token, a pointer to a WBXMLAttrEntry structure.
  • WBXML_VALUE_LITERAL - In this case, the Tag Name is a literal, a pointer to a WBXMLBuffer structure.

        typedef struct WBXMLAttribute_s {
            WBXMLAttributeName  *name;  /* Attribute Name */
            WBXMLBuffer *value;         /* Full Attribute Value */
        } WBXMLAttribute;
                            
The WBXMLAttribute contains:
  • An Attribute Name : A WBXMLAttributeName structure.
  • An Attribute Value : A WBXMLBuffer structure.

[Warning]Warning


    The 'value' part of an WBXMLAttribute contain the FULL attribute value.
    For example, with the attribute: url="http://127.0.0.1/"
    if the 'name' part is this:
        - name->u.token->wbxmlCodePage: 0x00
        - name->u.token->wbxmlToken : 0x4b
        - name->u.token->xmlName : "url"
        - name->u.token->xmlValue: "http://"

    then, 'value' is still: "http://127.0.0.1/"

    Of course (in this example) it should be better to have the wbxmlToken 0x4a ("url" / NULL). So you mustn't take into
    account the 'xmlValue' field for 'name' to get the Attribute Value of this Attribute.
                                

wbxml_tree

This module define a WBXML Tree. This is the main in-memory representation of a WBXML Document, used by the WBXML Parser and the WBXML Encoder.

A WBXML Tree is composed of WBXML Nodes which can be: an Element Node, a Text Node or a PI Node.

        typedef enum WBXMLTreeNodeType_e
        {
            WBXML_TREE_ELEMENT_NODE = 0, /* Element Node */
            WBXML_TREE_TEXT_NODE,        /* Text Node */
            WBXML_TREE_PI_NODE,          /* PI Node */
        } WBXMLTreeNodeType;
                            

A WBXMLTreeAttribute is a structure that permits to chain several WBXMLAttribute structures into a List.

        typedef struct WBXMLTreeAttribute_s
        {
            WBXMLAttribute  *attr;              /* Attribute */
            struct WBXMLTreeAttribute_s  *next; /* Next attribute */
        } WBXMLTreeAttribute;
                            

A WBXML Tree is composed of WBXML Nodes.

        typedef struct WBXMLTreeNode_s
        {
            WBXMLTreeNodeType   type;       /* Node Type */
            WBXMLTag            *name;      /* Node Name (if type is 'WBXML_TREE_ELEMENT_NODE') */
            WBXMLTreeAttribute  *attrs;     /* Node Attributes (if type is 'WBXML_TREE_ELEMENT_NODE') */
            WBXMLBuffer         *content;   /* Node Content (if  type is 'WBXML_TREE_TEXT_NODE')  */
                
            struct WBXMLTreeNode_s  *parent;    /* Parent Node */
            struct WBXMLTreeNode_s  *children;  /* Children Node */
            struct WBXMLTreeNode_s  *next;      /* Next sibling Node */
            struct WBXMLTreeNode_s  *prev;      /* Previous sibling Node */
        } WBXMLTreeNode;
                            

Finally, a WBXML Tree defines a WBXM Language and a root WBXML Node.

        typedef struct WBXMLTree_s
        {    
            const WBXMLLangEntry  *lang; /* Language Table */
            WBXMLTreeNode   *root;       /* Root Element */
        } WBXMLTree;
                            

wbxml_encoder

The WBXML Encoder is used to encode a WBXML Tree into:

Cf. the Reference Chapter for more informations about this functions.

wbxml_parser

The WBXML Parser can be used in two ways:

Cf. the Reference Chapter for more informations about this functions.

There are two ways of using the WBXML Parser

  • Parse a WBXML Document into a WBXML Tree : wbxml_parser_parse_to_tree()
  • Parse a WBXML Document into your own internal structures, by implementing your own Parser Callbacks : wbxml_parser_parse()

This functions are used to initialise the Parser.

A WBXMLContentHandler is a structure that defines all the Callback Functions.

        typedef struct WBXMLContentHandler_s {
            WBXMLStartDocumentHandler start_document_clb;       /* Start Document Handler */
            WBXMLEndDocumentHandler end_document_clb;           /* End Document handler */
            WBXMLStartElementHandler start_element_clb;         /* Start Element handler */
            WBXMLEndElementHandler end_element_clb;             /* End Element handler */
            WBXMLCharactersHandler characters_clb;              /* Characters handler */
            WBXMLProcessingInstructionHandler pi_clb;           /* Processing Instruction Handler */
        } WBXMLContentHandler;
                            

  • void WBXMLStartDocumentHandler(ctx, charset, lang);
    void *ctx;
    WB_LONGcharset;
    const WBXMLLangEntry *lang;

    This Callback function is called when starting to parse the WBXML document.

    • ctx: The User Data
    • charset: IANA Charset MIBenum of the WBXML document
    • lang: WBXML Language Table (defined in wbxml_tables.[h|c])

  • void WBXMLEndDocumentHandler(ctx);
    void *ctx;

    This Callback function is called when finished to parse the WBXML document. The parameter is the User Data.

  • void WBXMLStartElementHandler(ctx, localName, atts, empty);
    void *ctx;
    WBXMLTag *localName;
    WBXMLAttribute **atts;
    WB_BOOLempty;

    This Callback function is called when parsing a WBXML start Element.

    • ctx: The User Data
    • localName: The WBXML Tag
    • atts: The WBXML Attribute list
    • empty: TRUE if this is an empty Element, FALSE otherwise

  • void WBXMLEndElementHandler(ctx, localName, empty);
    void *ctx;
    WBXMLTag *localName;
    WB_BOOLempty;

    This Callback function is called when parsing a WBXML end Element.

    • ctx: The User Data
    • localName: The WBXML Tag
    • empty: TRUE if this is an empty Element, FALSE otherwise

  • void WBXMLCharactersHandler(ctx, ch, start, length);
    void *ctx;
    WB_UTINY *ch;
    WB_ULONGstart;
    WB_ULONGlength;

    This Callback function is called when parsing a Content Data.

    • ctx: The User Data
    • ch: Buffer of character data
    • start: Starting index in Buffer
    • length: Length of data

  • void WBXMLProcessingInstructionHandler(ctx, target, data);
    void *ctx;
    const WB_UTINY *target;
    WB_UTINY *data;

    This Callback function is called when parsing a Processing Instruction.

    • ctx: The User Data
    • target: The processing instruction target
    • data: The processing instruction data

Example 4.4. WBXML Parser use

        #include <string.h>
        #include <wbxml.h>
        
        #define INPUT_BUFFER_SIZE 1000
        
        
        /** Start Document Callback */
        void parse_clb_start_document(void *ctx, WB_LONG charset, const WBXMLLangEntry *lang)
        {
            printf("Parsing Document:\n"
                   "\tRoot Element: %s\n"
                   "\tPublic ID: %s\n"
                   "\tDTD: %s\n",
                   lang->publicID->xmlRootElt,
                   lang->publicID->xmlPublicID,
                   lang->publicID->xmlDTD);
        }
        
        /** End Document Callback */
        void parse_clb_end_document(void *ctx)
        {
            printf("End of Document\n");
        }
        
        /** Start Element Callback */
        void parse_clb_start_element(void *ctx, WBXMLTag *element, WBXMLAttribute **atts, WB_BOOL empty)
        {    
            WB_ULONG *indent = (WB_ULONG *) ctx;
            
            WB_ULONG i = 0, j = 0;
            
            /* Indent start Element */
            for (i=0; i<*indent; i++)
                printf(" ");
        
            /* Write start Element */
            printf("<%s", wbxml_tag_get_xml_name(element));
            
            /* Write Attributes */
            if (atts != NULL) {
                while (atts[j] != NULL)
                {
                    /* Write Attribute Name */
                    printf(" %s=\"%s\"", wbxml_attribute_get_xml_name(atts[j]), wbxml_attribute_get_xml_value(atts[j]));  
                    j++;
                }        
            }
            
            /* End of start Element */
            if (empty) {
                printf("/>\n");
            }
            else {
                printf(">\n");
                (*indent)++;
            }
        }
        
        /** End Element Callback */
        void parse_clb_end_element(void *ctx, WBXMLTag *element, WB_BOOL empty)
        {
            WB_ULONG *indent = (WB_ULONG *) ctx;
            WB_ULONG i = 0;
        
            if (!empty) {
                (*indent)--;
        
                /* Indent End Element */
                for (i=0; i<*indent; i++)
                    printf(" ");
                    
                /* Write end tag */
                printf("</%s>\n", wbxml_tag_get_xml_name(element));        
            }
        }
        
        /** Characters Callback */
        void parse_clb_characters(void *ctx, WB_UTINY *ch, WB_ULONG start, WB_ULONG length)
        {
            WB_ULONG *indent = (WB_ULONG *) ctx;
            WB_ULONG i = 0;
            
            /* Indent Characters */
            for (i=0; i<*indent; i++)
                printf(" ");
        
            /* Write Content */
            for(i=start; i<length; i++)
                printf("%c", ch[i]);
        
            printf("\n");
        }
        
        /** Main Function */
        WB_LONG main(WB_LONG argc, WB_TINY **argv) 
        {
            FILE *input_file = NULL;
            WB_ULONG count = 0, total = 0, wbxml_len = 0;
            WB_UTINY input_buffer[INPUT_BUFFER_SIZE + 1];
        
            WBXMLParser *wbxml_parser = NULL;
            WB_UTINY *wbxml = NULL;
            WB_ULONG indent = 0, error_index = 0;
            WBXMLError ret = WBXML_OK;
            WBXMLContentHandler parse_handler = 
                {
                    parse_clb_start_document,
                    parse_clb_end_document,
                    parse_clb_start_element,
                    parse_clb_end_element,
                    parse_clb_characters,
                    NULL
                };
                
            if (argc != 2) {
                printf("Missing argument: WBXML Filename");
                return 0;
            }
        
            /**********************************
             *  Read the WBXML Document
             */
        
            /* Open WBXML document */
            if ((input_file = fopen(argv[1], "rb")) == NULL) {
                printf("Failed to open %s\n", argv[1]);
                return 0;
            }
        
            /* Read WBXML document */
            while(!feof(input_file))    {
                count = fread(input_buffer, sizeof(WB_UTINY), INPUT_BUFFER_SIZE, input_file);
                if (ferror(input_file))      {
                    printf("Error while reading from file %s\n", argv[1]);
                    fclose(input_file);
                    if (wbxml != NULL)
                        wbxml_free(wbxml);
                    return 0;
                }
        
                total += count;
                if ((wbxml = wbxml_realloc(wbxml, total)) == NULL) {
                    printf("Not enought memory\n");
                    fclose(input_file);
                    if (wbxml != NULL)
                        wbxml_free(wbxml);
                    return 0;
                }
        
                memcpy(wbxml + wbxml_len, input_buffer, count);
                wbxml_len += count;
            }
        
            fclose(input_file);
            
            /* Create WBXML Parser */
            if ((wbxml_parser = wbxml_parser_create()) == NULL) {
                wbxml_free(wbxml);
                return 0;
            }
            
            /* Initialize WBXML Parser */
            wbxml_parser_set_user_data(wbxml_parser, &indent);
            wbxml_parser_set_content_handler(wbxml_parser, &parse_handler);
            
            /* Parse WBXML document */
            if ((ret = wbxml_parser_parse(wbxml_parser, wbxml, wbxml_len)) != WBXML_OK)
            {
                error_index = wbxml_parser_get_current_byte_index(wbxml_parser);
                printf("Parsing failed at %u - Token %x - %s", error_index, wbxml[error_index], wbxml_errors_string(ret));
            }
            else {
                printf("Parsing OK !");          
            }
            
            /* Destroy WBXML Parser */
            wbxml_parser_destroy(wbxml_parser);
        
            /* Free wbxml buffer */
            wbxml_free(wbxml);
        
            return 0;
        }
                        

This functions permit to convert directly XML to WBXML, and WBXML to XML.

Copyright İ 2003 Aymerick Jéhanne All rights reserved. http://wbxmllib.jehanne.org