XBinder icon XBinder

XML TO CODE GENERATION TOOL

Efficient, Low Cost XML Data Binding and XML to Code Generation Speeds Your Project's Time-To-Market

The complexity of producing well constructed, reliable class libraries from XML schema can challenge any project's timeline and staff productivity. The XBinder XSD code generation tool substantially streamlines and simplifies a project's development and maintenance time by automatically serializing objects into XML and deserializing XML into C, C++, Java, or C# objects based on XML schema (XSD) files.

XBinder data flow


Why use an XML Data Binding or XML to Code Generation Tool?

XBinder's XML data binding offers the following advantages over traditional XML API's such as SAX and DOM:

Performance - Operations such as validation or (de)serialization are faster with code generated from XML schema then with validating parsers.

Simplicity - XBinder automates production of well constructed, easy-to-read code for faster time-to-market cycles.

Reliability - XML data binding applications assure the validity of generated XML documents by working at the schema level.

Overview of XBinder

XBinder is an XML Schema to C/C++, Java, or C# code generation tool. XML data binding (or code generation) is a process in which XML schema information items are transformed into type definitions and functions in a computer language.

The source code produced by the XBinder code generation tool is C, C++, Java, or C# source code that consists of type definitions and encode/decode functions. This provides a complete Application Programming Interface (API) for working with all of the message definitions contained within an XML schema specification.

In addition to the code generator, a run-time library of common encode/decode functions is also part of the package. This library contains routines to encode and decode the base XML schema simple types (integer, string, hexBinary, etc.). The XBinder code generation tool assembles a series of calls to these functions to accomplish the encoding or decoding of more complex message types.

Evaluation versions are available for Windows, Linux, various UNIX platforms, and Apple Mac OSX.

XSD to Source Code

Further details on the source code generation capabilities of XSD for specific languages can be found at the following links:

XSD to C/C++

XSD to Java

XSD to C#

Suppose you needed to write code to parse through the XML instance below and print out all of the data that's contained within it.


        <purchase>
          <customer number="12345">
            John Smith
          </customer>
          <store>
            Toys R Us
          </store>
          <item>
            Toy Bath Set
          </item>
          <price>
            19.95
          </price>
        </purchase>
      

On this page we'll compare the amount of code that would be necessary to parse through this instance without XBinder with the amount of code that would be necessary to do the parsing with XBinder. We'll use C++ for both examples. For the non-XBinder code we'll use the DOM capabilities of libxml++.

Below is the code that would need to be written if XBinder is not being used:


       #include <libxml++/libxml++.h>
       #include <stdio.h>

       int main()
       {
          // Parse the XML file.
          xmlpp::DomParser parser;
          parser.set_substitute_entities();
          try
          {
             parser.parse_file("purchase.xml");
          }
          catch (std::exception& ex)
          {
             printf("\n%s", ex.what());
          }

          // Get the root node.
          xmlpp::Node* pPurchaseNode = parser.get_document()->get_root_node();
          Glib::ustring nodename = pPurchaseNode->get_name();

          // Get the root node's children in a list.
          xmlpp::Node::NodeList purchaseChildren = pPurchaseNode->get_children();

          // Now walk through the children and process them according to what element
          // is represented.
          for (xmlpp::Node::NodeList::iterator iter = purchaseChildren.begin();
          iter != purchaseChildren.end(); ++iter)
          {
             xmlpp::Node* pChildNode = *iter;
             nodename = pChildNode->get_name();

             if (nodename == "text")
             {
                // We'll get the text value for each element explicitly
                // as we encounter them.
                continue;
             }
             else if (nodename == "customer")
             {
                // We're at the <customer> node.  We want to print the customer
                // name and number.
                xmlpp::Element* pChildElement =
                   dynamic_cast<xmlpp::Element*> (pChildNode);
                xmlpp::Attribute* pCustomerAttr =
                   pChildElement->get_attribute("number");
                printf("\nCustomer number:  %s", pCustomerAttr->get_value().c_str());

                xmlpp::TextNode* pChildText = pChildElement->get_child_text();
                printf("\nCustomer name:  %s", pChildText->get_content().c_str());
             }
             else if (nodename == "store")
             {
                // We're at the <store> node.  We want to print the store name.
                xmlpp::Element* pChildElement =
                   dynamic_cast<xmlpp::Element*> (pChildNode);
                xmlpp::TextNode* pChildText = pChildElement->get_child_text();
                printf("\nStore name:  %s", pChildText->get_content().c_str());
             }
             else if (nodename == "item")
             {
                // We're at the <item> node.  We want to print the item name.
                xmlpp::Element* pChildElement =
                   dynamic_cast<xmlpp::Element*> (pChildNode);
                xmlpp::TextNode* pChildText = pChildElement->get_child_text();
                printf("\nItem name:  %s", pChildText->get_content().c_str());
             }
             else if (nodename == "price")
             {
                // We're at the <price> node.  We want to print the price.
                xmlpp::Element* pChildElement =
                   dynamic_cast<xmlpp::Element*> (pChildNode);
                xmlpp::TextNode* pChildText = pChildElement->get_child_text();
                printf("\nPrice:  %s", pChildText->get_content().c_str());
             }
          }

          return 0;
       }
     
   

And below is the code that would need to be written using XBinder:

      
       #include "rtxsrc/OSRTFileInputStream.h"
       #include "rtxmlsrc/rtXmlCppMsgBuf.h"
       #include <Purchase.h>
       #include <stdio.h>

       int main()
       {
          // Setup to decode the instance in purchase.xml
          int stat;
          const char* filename = "Purchase.xml";
          OSRTFileInputStream in (filename);
          OSXMLDecodeBuffer decodeBuffer (in);
          purchase_CC pdu (decodeBuffer);

          // Do the decode
          stat = pdu.decode();

          // Print the information that was in the instance.
          PurchaseRecord* pPurchase = pdu.getValue();
          printf("\nCustomer number:  %d", pPurchase->customer.number);
          printf("\nCustomer name:  %s", pPurchase->customer.value.c_str());
          printf("\nStore name:  %s", pPurchase->store.c_str());
          PurchaseRecord_3* pItemAndPrice = pPurchase->_seq3.getItem(0);
          unsigned short i = 0;
          while (pItemAndPrice != 0)
          {
             printf("\nItem name:  %s", pItemAndPrice->item.c_str());
             printf("\nItem price:  %.2f", pItemAndPrice->price);
             pItemAndPrice = pPurchase->_seq3.getItem(++i);
          }
          return stat;
       }
     
   

A couple of things about these code samples are worth noting:

  • The code that does not use XBinder is about twice as long as the code that does use it.
  • The amount of knowledge about the structure of the XML instance that the author of the code must have is substantially reduced with XBinder. For this simple instance the author of the code needs almost no knowledge of the XML structure if he is using XBinder.
  • The code that does not use XBinder is not doing any validation of the XML grammar. For instance, if the schema associated with this instance stipulates that the <store> element must follow the <customer> element, that constraint is not checked. Adding this type of checking would make the non-XBinder code quite a bit longer than it is already! Schema-based grammar reinforcement is done by XBinder in the decode process. A simple check of the value of the stat variable in the XBinder example is all that would need to be added to the XBinder-based code.

XBinder 2.9.0 is the current production release. This version was released on 29 November 2023.

XBinder features now include:

  • Support for all recent Visual Studio versions up to and including 2022.
  • Linux distributions now include both 64 and 32-bit libraries compiled with GCC versions 4 through 10.
  • The capability to integrate more effectively with Qt applications.
  • XML validation. The XBinder Editor now has the ability to validate XML documents against XML Schema.
  • The capability of groups to include repeating elements and wildcards in XML Schema 1.1
  • Capability to generate code in four different languages (C, C++, Java, and C#) included in base package.

 

Purchase Download