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>
Rubber Ducky 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 number
// and the customer name.
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;
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
statvariable in the XBinder example is all that would need to be added to the XBinder-based code.

