Simple XML example in C++

Like most developers, I have tons of small code samples and snippets lying around.  I’m starting to go through them in order to post what might be useful to others.

Here’s one that I wrote about 5 years ago when I had a customer complaining about the speed of parsing an XML document using MSXML.  Of course this test simply confirmed that yes, MSXML is molasses-in-January slow and that if raw speed is what you want, then something like Expat is a better route to go.  However the test is a reasonably good sample of how you might use the DOMDocument from a C++ application.

As always, the code is an as-is sample.  uSe it at your own risk.

#include <windows.h>
#include “objbase.h”
#include “oleauto.h”
#include “MSXML.h”
#include “ATLBASE.h”
#import “msxml.dll” named_guids raw_interfaces_only

TCHAR *xmlfile = _T(“\test.xml”);
using namespace MSXML;

void GetCurrentDirectory(TCHAR *szDirectory);

int WINAPI WinMain(    HINSTANCE hInstance,
                    HINSTANCE hPrevInstance,
                    LPTSTR lpCmdLine,
                    int nCmdShow)
    MSXML::IXMLDOMDocument      *iXMLDoc          = NULL;
    HRESULT                     hr;
    VARIANT_BOOL                b;
    int                         et                = 0;
    HANDLE                      hFile             = NULL;
    DWORD                       wsize, dwhigh     = 0;
    TCHAR                       filename[MAX_PATH];
    MEMORYSTATUS                ms;
    BYTE                        *buffer           = NULL;
    TCHAR                       *wbuffer          = NULL;
    DWORD                       dwRead            = 0;
    DWORD                       toalloc           = 0;
    int                         i;
    CComBSTR                    *bstr;

    _tprintf(_T(“Starting XML Benchmark…n”));
    _tprintf(_T(“Creating DOMDocument…”));

    // start COM

    // create a DOMDocument
    hr = CoCreateInstance (MSXML::CLSID_DOMDocument, NULL,
                 MSXML::IID_IXMLDOMDocument,(LPVOID *)&iXMLDoc);

    // check for success
        _tprintf(_T(“failed (hr = %i)n”), hr);
        goto exit;


    // synchronous operation

    // get the data file – pull from the same directory as our app
    _tcscat(filename, xmlfile);
    _tprintf(_T(“Opening XML file (%s)…”), filename);


        _tprintf(_T(“failed (err = %i)n”), GetLastError());
        goto exit;

    // determine the file size
    dwsize = GetFileSize(hFile, &dwhigh);


    // check available memory
    ms.dwLength = sizeof(MEMORYSTATUS);

    // either 1/3 available memory or file size, whichever is less
    toalloc = (dwsize > (ms.dwAvailPhys / 3)) ? (ms.dwAvailPhys / 3) : dwsize;

    _tprintf(_T(“Allocating %i bytes…”), toalloc);
    //alocate buffers. data is ANSI, loadXML requires Unicode
    buffer = (BYTE *)LocalAlloc(LPTR, toalloc);
    wbuffer = (TCHAR *)LocalAlloc(LPTR, toalloc * sizeof(TCHAR) + 1);

    // check for success
    if((buffer == NULL) || (wbuffer == NULL))
        _tprintf(_T(“failed (err = %i)n”), GetLastError());
        goto exit;

    _tprintf(_T(“oknReading %i bytes…”), toalloc);
    // fill the RAM buffer with data
    ReadFile(hFile, &buffer[0], toalloc, &dwRead, NULL);

    // lazy man’s ANSI to Unicode conversion
    // this is NOT recommended for production code, don’t cut and paste!!
    for(i = 0 ; i < (int)toalloc ; i++)
        wbuffer[i] = buffer[i];
    wbuffer[i] = ”;
    bstr = new CComBSTR(wbuffer);

    _tprintf(_T(“oknLoading %i bytes into DOMDocument…”), toalloc);

    // get a start time
    et = GetTickCount();

    // load the xml
    hr = iXMLDoc->loadXML(*bstr, &b);

    // determine ET
    et = GetTickCount() et;

    // check for load failure
        _tprintf(_T(“failed (hr = %i)n”), hr);
        _tprintf(_T(“GetLastError = %in”), GetLastError());
        goto exit;

    _tprintf(_T(“done.nnET = %i msnn”), et);

    // release the DOMDocument

    // release the file

    // release COM

    _tprintf(_T(“Exiting XML Benchmark in 5 seconds…n”));
    // free buffers

    // wait to allow display to persist for a while

    return 0;

void GetCurrentDirectory(TCHAR *szDirectory)
    TCHAR *p, *p2;

    // get current directory
    GetModuleFileName(NULL, szDirectory, MAX_PATH);

    // trim off the exe name
    p = _tcsstr(szDirectory, _T(“\”));

    if(p == NULL)
        // no slash found – return root?
        _tcscpy(szDirectory, _T(“\”));

    while( p != NULL)
        p2 = p + 1;
        p = _tcsstr(p2, _T(“\”));

    // null terminate to crop
    *p2 = ”;


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s