FoodForFutureGeeks

Thursday 2 May 2013

XML Writer In C++ using Xerces-DOM

The following program demonstrates how to write an XML file in C++:


/*********************************
* author: Aniruddha S N
*
* description:
* The main function uses a DOM implementation 
* to construct a DOM tree, once the dom tree is completely constructed
* it invokes the mserialiser_XML_Writer method to Serilize the DOM tree
* and write it to a xml file.
*
* Dependency: xerces3.1-c (code not compatible with older versions of xerces.)
*/
 
 
#include<iostream>
#include<vector>
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/dom/DOM.hpp>
#include <xercesc/framework/StdOutFormatTarget.hpp>
#include <xercesc/framework/LocalFileFormatTarget.hpp>
#include <time.h>
#include <string>
#include <sstream>
void Serialiser_XML_writer(xercesc::DOMDocument* pDOMDocument, char* FullFilePath );
 
using namespace std;
//below macro gives all the required namespaces for Xerces
XERCES_CPP_NAMESPACE_USE
 
 
 
 
 
 
 
 
void main()
{
 
XMLPlatformUtils::Initialize();
 
// Pointer to our DOMImplementation.
DOMImplementation * pDOMImplementation = NULL;
 
// Get the DOM Implementation (used for creating DOMDocuments).
// Also see: http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html
pDOMImplementation = 
  DOMImplementationRegistry::getDOMImplementation(XMLString::transcode("core"));
 
DOMDocument * pDOMDocument = NULL;
 
pDOMDocument = pDOMImplementation-&gt;createDocument(L"schemas.example.com/2008/", 
                                                  L"ex:Hello_World", 0);
 
 
DOMElement * pRootElement = NULL;
pRootElement = pDOMDocument-&gt;getDocumentElement();
 
 
// Create a Comment node, and then append this to the root element.
DOMComment * pDOMComment = NULL;
pDOMComment = pDOMDocument-&gt;createComment(L"Dates are formatted mm/dd/yy." 
              L" Don't forget XML is case-sensitive.");
pRootElement-&gt;appendChild(pDOMComment);
 
 
// Create an Element node, then fill in some attributes,
// and then append this to the root element.
DOMElement * pDataElement = NULL;
pDataElement = pDOMDocument-&gt;createElement(L"data");
 
    // Copy the current system date to a buffer, then set/create the attribute.
    wchar_t wcharBuffer[128];
    _wstrdate_s(wcharBuffer, 9);
    pDataElement-&gt;setAttribute(L"date", wcharBuffer);
 
    // Convert an integer to a string, then set/create the attribute.
    _itow_s(65536, wcharBuffer, 128, 10);
    pDataElement-&gt;setAttribute(L"integer", wcharBuffer);
 
    // Convert a floating-point number to a wstring,
    // then set/create the attribute.
    std::wstringstream    myStream;
        myStream.precision(8);
        myStream.setf(std::ios_base::fixed, std::ios_base::floatfield);
        myStream &lt;&lt; 3.1415926535897932384626433832795;
    const std::wstring ws(myStream.str());
    pDataElement-&gt;setAttribute(L"float", ws.c_str());
    
    // Append 'pDataElement' to 'pRootElement'.
    pRootElement-&gt;appendChild(pDataElement);
 
 
// Create an Element node, then fill in some attributes, add some text,
// then append this to the 'pDataElement' element.
DOMElement * pRow = NULL;
pRow = pDOMDocument-&gt;createElement(L"tow");
 
    // Create some sample data.
    _itow_s(1, wcharBuffer, 128, 10);
    pRow-&gt;setAttribute(L"index", wcharBuffer);
 
    /*
    Create a text node and append this as well. Some people 
    prefer to place their data in the text node
    which is perfectly valid, others prefer to use 
    the attributes. A combination of the two is quite common.
    */
    DOMText* pTextNode = NULL;
    pTextNode = pDOMDocument-&gt;createTextNode(L"Comments and" 
                L" data can also go in text nodes.");
    pRow-&gt;appendChild(pTextNode);
    pDataElement-&gt;appendChild(pRow);
 
 
// Create a new  row (this time putting data and descriptions into different places).
pRow = pDOMDocument-&gt;createElement(L"ConstantPI");
    pRow-&gt;setAttribute(L"description", L"The value of PI");
    pTextNode = pDOMDocument-&gt;createTextNode(L"3.1415");
    pRow-&gt;appendChild(pTextNode);
    pDataElement-&gt;appendChild(pRow);
 
 
// Create a new row.
pRow = pDOMDocument-&gt;createElement(L"UsefulLinks");
    pRow-&gt;setAttribute(L"website", L"http://www.programminggeeksinchrysalis.blogspot.com/");
    pTextNode = pDOMDocument-&gt;createTextNode(L"Blog worth Reading.");
    pRow-&gt;appendChild(pTextNode);
    pDataElement-&gt;appendChild(pRow);
    char* path="c:\\temp\\sample.xml";
    Serialiser_XML_writer(pDOMDocument,path);
 
//Release The Document after the xml file has been written
    pDOMDocument-&gt;release();
    XMLPlatformUtils::Terminate();
    }
 
 


Method XML writer:


/*****************************************
* author: Aniruddha S N
*
* Description: the function serializes the DOM tree 
* and writes it in XML form to the mentioned file.
*
*/
 
#include <iostream>
#include <vector>
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/dom/DOM.hpp>
#include <xercesc/framework/StdOutFormatTarget.hpp>
#include <xercesc/framework/LocalFileFormatTarget.hpp>
#include <time.h>
#include <string>
#include <sstream>
using namespace std;
//below macro gives all the required namespaces for Xerces
XERCES_CPP_NAMESPACE_USE
 
void Serialiser_XML_writer(xercesc::DOMDocument* pDOMDocument, char* FullFilePath )
{
DOMImplementation *pImplement = NULL;
DOMLSSerializer *pSerializer = NULL; // @DOMWriter
LocalFileFormatTarget *pTarget = NULL; 
 
//Return the first registered implementation that has the desired features. In this case, we are after
//a DOM implementation that has the LS feature... or Load/Save.
 
pImplement = DOMImplementationRegistry::getDOMImplementation(L"LS");
 
//From the DOMImplementation, create a DOMWriter.
//DOMWriters are used to serialize a DOM tree [back] into an XML document.
 
pSerializer = ((DOMImplementationLS*)pImplement)-&gt;createLSSerializer(); 
DOMLSOutput *pOutput = ((DOMImplementationLS*)pImplement)-&gt;createLSOutput();
DOMConfiguration *pConfiguration = pSerializer-&gt;getDomConfig();
 
// Have a nice output
if (pConfiguration-&gt;canSetParameter(XMLUni::fgDOMWRTFormatPrettyPrint, true))
pConfiguration-&gt;setParameter(XMLUni::fgDOMWRTFormatPrettyPrint, true); 
pTarget = new LocalFileFormatTarget(FullFilePath);
pOutput-&gt;setByteStream(pTarget);
 
//pSerializer->write(pDOMDocument->getDocumentElement(), pOutput); // missing header "" if used
pSerializer-&gt;write(pDOMDocument, pOutput); 
 
delete pTarget;
pOutput-&gt;release();
pSerializer-&gt;release();
}
 


Output File:


<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<ex:Hello_World xmlns:ex="schemas.example.com/2008/">

  <!--Dates are formatted mm/dd/yy. Don't forget XML is case-sensitive.-->

  <data date="05/02/13" float="3.14159265" integer="65536">
    <tow index="1">Comments and data can also go in text nodes.</tow>
    <ConstantPI description="The value of PI">3.1415</ConstantPI>
    <UsefulLinks website="http://www.programminggeeksinchrysalis.blogspot.com/">Blog worth Reading.</UsefulLinks>
  </data>

</ex:Hello_World>