Home Search Contact us About us
Title How to create and parse a simple XML document using MSXML.dll
Summary Most developers would be able to create and even parse an XML packet using simple string manupulation. Hovever the MSXML DOM make the task trival and enable the development, manipulation and parsing of very complex XML documents.
Contributor Anson Cheung and John McTainsh
Published 24-May-2001
Last updated 24-May-2001
Page rating   71% for 47 votes Useless Brilliant

Description.

XML is becoming a popular way to pass complex data in a mostly human readable form. In the article we will discuss how to create an XML document then parse the document to get particular data out of it. It is quite easy to create XML using simple text strings but we will use the very powerful MSXML Document Object Model. Remember, DOM is goood.

What is a XML

As MSDN would say "XML is the universal language for describing and exchanging data". For more detail see.

For this article it is something that looks like this UsingXmlDom.xml file.

What we need to get started

Microsoft has a COM object called the Microsoft MSXML Parser tool to create and parse XML. To use this we need to add the following code to stdafx.
// Stdafx.h
#import "msxml.dll"
using namespace MSXML;

void CheckHR( HRESULT hr );

...

// Stdafx.cpp
// ***************************************************************************
//DESCRIPTION:
//      Check the hresult and throw it in an execption if unsucessfull. 
//CREATED:
//      25-5-2001, 6:49:32 PM by john@mctainsh.com
// ***************************************************************************
void CheckHR( HRESULT hr )
{
    if( FAILED(hr) )
        _com_issue_error(hr);
}

Because we are working with COM will also need to call CoInitialize(NULL); and CoUninitialize(); in our code and start-up and shutdown.

Some handy functions

When building XML documents and working with COM, I have found the following functions very handy. They can be added to the code above where they are called. The first just converts a COM execption into a MessageBox. The second and third are used add data to the XML document.

// **************************************************************************
//  DESCRIPTION:
//      Display any com error in a MessageBox.
//  CREATED:
//      04-04-2001, 023:06pm by Anson Cheung
// ***************************************************************************
void ComErrorMessageBox(_com_error &e)
{
    bstr_t bstrSource(e.Source());
    bstr_t bstrDescription(e.Description());

    CString sErr, sOutMessage;
    sErr.Format( _T("Code = 0x%08lx\n"), e.Error());
    sOutMessage += sErr;
    sErr.Format( _T("Code meaning = %s\n"), e.ErrorMessage());
    sOutMessage += sErr;
    sErr.Format( _T("IErrorInfo.Source = %s\n"), (LPTSTR)bstrSource );
    sOutMessage += sErr;
    sErr.Format( _T("IErrorInfo.Description = %s"), (LPTSTR)bstrDescription );
    sOutMessage += sErr;
    AfxMessageBox( sOutMessage );
}

//Disable error The identifier string exceeded the maximum allowable length and was truncated.
#pragma warning(disable:4786) 

// ***************************************************************************
//DESCRIPTION:
//      Start a new XML element.
//PARAMS:
//      sNodeName   The new node name.
//      pNode       The node to add the new node to.
//RETURN:
//      The Node base or the new element.
//CREATED:
//      23-5-2001, 16:27:11 by john@mctainsh.com
// ***************************************************************************
IXMLDOMNodePtr StartXmlElement( CString sNodeName, IXMLDOMNodePtr pParentNode )
{
    ASSERT( pParentNode != NULL );
    //NODE_ELEMENT
    VARIANT v;
    V_VT(&v) = VT_I4;
    V_I4(&v) = 1;

    //Get access to the Document (Will be NULL if it is the root)
    IXMLDOMDocumentPtr pXMLDoc = pParentNode->ownerDocument;
    if( pXMLDoc == NULL )
        pXMLDoc = pParentNode;
         
    //Create the element
    IXMLDOMNodePtr pNodeNew = pXMLDoc->createNode(v, (bstr_t)sNodeName, _T("") );
    ASSERT( pNodeNew != NULL );

    //append it to the parent branch
    pParentNode->appendChild( pNodeNew );           
    return pNodeNew;
}


// ***************************************************************************
//DESCRIPTION:
//      Add Attributes to the Given Element.
//PARAMS:
//      sAttribute  The title of the Atttribute.
//      sValue      The value of the attribute.
//      pNode       The node to add the attributes to.
//CREATED:
//      23-5-2001, 16:27:11 by john@mctainsh.com
// ***************************************************************************
void AddXmlAttribute( CString sAttribute, CString sValue, IXMLDOMNodePtr pNode )
{
    ASSERT( pNode != NULL );
    // NODE_ATTRIBUTE
    VARIANT v;
    V_VT(&v) = VT_I4;
    V_I4(&v) = 2;

    //Get access to the Attributes Map
    IXMLDOMNamedNodeMapPtr pCurrentAttrs = NULL;
    CheckHR( pNode->get_attributes( &pCurrentAttrs) );
    ASSERT( pCurrentAttrs != NULL );

    //Get access to the Document (Will be NULL if it is the root)
    IXMLDOMDocumentPtr pXMLDoc = pNode->ownerDocument;
    if( pXMLDoc == NULL )
        pXMLDoc = pNode;

    //Create a new attribute in the document
    IXMLDOMNodePtr pNodeNew = pXMLDoc->createNode( v, (bstr_t)sAttribute, "");
    ASSERT( pNodeNew != NULL );

    //Assign the text and attach to the attributes
    pNodeNew->Puttext( (bstr_t)sValue );
    pCurrentAttrs->setNamedItem( pNodeNew );
}

Building an XML document.

Now lets build the XML document here. Some parts of this are optional. ie The Processing Instruction and the Comment. Note that at then end the XML document may be accessed as a string or saved to a file.

// ***************************************************************************
//DESCRIPTION:
//      Fill and XML packet of Data.
//CREATED:
//      23-5-2001, 15:00:03 by john@mctainsh.com
// ***************************************************************************
void CDlgOutXML::OnBtnBuild() 
{   
    try
    {
        //Create the XML Document
        IXMLDOMDocumentPtr pXMLDoc(__uuidof(DOMDocument)); 


        //Add the Process instruction to the top of the document, "Optional"
        IXMLDOMProcessingInstructionPtr pProInstrut= pXMLDoc->createProcessingInstruction(
                    _T("xml"), 
                    _T("version='1.0'") );
        ASSERT( pProInstrut != NULL );
        ASSERT( pXMLDoc->appendChild( pProInstrut ) != NULL );

        //Add some comments to the document, "Optional"
        IXMLDOMCommentPtr pComment = pXMLDoc->createComment ( _T("Some notes about people") );
        ASSERT( pComment != NULL );
        ASSERT( pXMLDoc->appendChild( pComment ) != NULL );
             
        //Create the root node
        IXMLDOMNodePtr pNodePeople = StartXmlElement( _T("People"), pXMLDoc );
        AddXmlAttribute( _T("Range"), _T("25km"), pNodePeople );

        //Create the Silly people node
        IXMLDOMNodePtr pNodeSillyPeople = StartXmlElement( _T("SillyPeople"), pNodePeople );
        IXMLDOMNodePtr pNodePerson = NULL;
        IXMLDOMNodePtr pNodePet = NULL;
        
            //Bill gates
            pNodePerson = StartXmlElement( _T("MyPerson"), pNodeSillyPeople );
            AddXmlAttribute( _T("Name"), _T("Mr Wal Mart"), pNodePerson );
            pNodePerson->text = _T("This is very rich man.");

                pNodePet = StartXmlElement( _T("ThePet"), pNodePerson );
                AddXmlAttribute( _T("Type"), _T("Dog"), pNodePet );
                AddXmlAttribute( _T("Breed"), _T("Jack Russel"), pNodePet );
                pNodePet->text = _T("Fox is his name.");


            //Tod stevens
            pNodePerson = StartXmlElement( _T("MyPerson"), pNodeSillyPeople );
            AddXmlAttribute( _T("Name"), _T("Tod"), pNodePerson );
            AddXmlAttribute( _T("Age"), _T("55"), pNodePerson );
            //pNodePerson->text = "Is a wally";
    

        //Create the brilliat people node
        IXMLDOMNodePtr pNodeCoolPeople = StartXmlElement( _T("BrilliantPeople"), pNodePeople );

            //John McTainsh
            pNodePerson = StartXmlElement( _T("MyPerson"), pNodeCoolPeople );
            AddXmlAttribute( _T("Name"), _T("John McTainsh"), pNodePerson );
            pNodePerson->text = _T("This is a very cool person.");

        //Save the XML data to a file or a string
        if( false )
            bstr_t bsXml = pXMLDoc->xml;
        else
            CheckHR( pXMLDoc->save( _T("out.xml") ) );

    }
    catch(_com_error &e)
    {
        ComErrorMessageBox(e);
    }
}       

Parsing the XML document.

Building XML is only half the story the things get interesting when we need to extract data from the XML document. In this example we will extract all the <MyPerson> elements. We will display the text for each element and all of its attributes. Note in this example there are three <MyPerson> elements in separate branches of the tree and that the IXMLDOMNodeListPtr object contains all elements.

// ***************************************************************************
//DESCRIPTION:
//      Parse the packet.
//CREATED:
//      23-5-2001, 14:49:45 by john@mctainsh.com
// ***************************************************************************
void CDlgOutXML::OnBtnParse() 
{
    try
    {
        //Create the XML Document
        IXMLDOMDocumentPtr pXMLDoc(__uuidof(DOMDocument)); 

        //Load the XML from a file or a string
        pXMLDoc->put_async(VARIANT_FALSE);
        if( false )
        {
            ASSERT( pXMLDoc->load( _T("out.xml") ) ); 
        }
        else
        {
            ASSERT( pXMLDoc->loadXML(
            _T( "<People>"
                "   <SillyPeople>"
                "       <MyPerson Name=\"Mr Wal Mart\">Rich man.</MyPerson>"
                "       <MyPerson Name=\"Tod\" Age=\"55\" />"
                "   </SillyPeople>"
                "   <BrilliantPeople>"
                "       <MyPerson Name=\"John McTainsh\">Is cool.</MyPerson> "
                "   </BrilliantPeople>"
                "</People>") ) );   
        }

        //Get the list of items we are looking for <MyPerson>
        bstr_t bsLookFor( _T("MyPerson") );
        IXMLDOMNodeListPtr pNodeList = pXMLDoc->getElementsByTagName( bsLookFor );

        int nList = pNodeList->length;
        TRACE( _T("Looking for = %s\n"), (LPTSTR)bsLookFor );
        TRACE( _T("Found %d items\n"), nList );

        //Iterate through each item found
        for( int n = 0; n < nList; n++ )
        {
            IXMLDOMNodePtr pNode = pNodeList->item[n];
            bstr_t bsNodeText = pNode->text;

            TRACE( _T("***************************\n") );
            TRACE( _T("Text = %s\n"), (LPTSTR)bsNodeText );

            IXMLDOMNamedNodeMapPtr pAttrs = pNode->attributes;
            long nAttrs = pAttrs->Getlength();

            //Iterate through each Attribute found
            for( long nAt = 0; nAt < nAttrs; nAt++ )
            {
                IXMLDOMNodePtr pAttb = pAttrs->Getitem( nAt );
                bstr_t bsAttbName = pAttb->nodeName;
                bstr_t bsAttbValue= pAttb->text;
                TRACE( _T("Attribute = %s is %s\n"), (LPTSTR)bsAttbName ,(LPTSTR)bsAttbValue );
            }
        }
    }
    catch(_com_error &e)
    {
        ComErrorMessageBox(e);
    }
}        
Comments Date
Best code for VC-XMLDOM 21-May-2002 Rahul gade
It is a best code i ever found over the net. I was searching for the same. actually i need was much more than this, but it help me in begining my coding.
Excellent !! work ...Help me a Lot..Thanks 21-Aug-2002 Raghavendra
Excellent !! work ...Help me a Lot..Thanks
The thing which i was searching i got
OK! Thanks! 11-Jan-2004 Nataris
I am from Russia. I looked information how I can insert Atribute into Node by means of createNode function. I have find it only your page. The grate THANKS!
Nataris.
How come the CDlgOutXML:: class scope? 22-Jun-2004 Leon Rasberry
Very good! However, where did the class notation come from on some of the methods (i.e. `CDlgOutXML::`).
11-Aug-2004
thankx for this code. It was what i need 11-Aug-2004 Seawolf
I look at a way to get all the information store in the xml file but, it`s hard to find descriptions of all functions of DOM API.
Now it works fine. But i need to get only the information of a specific node and not searching it in all the tree.
Thanks a ton. 5-Feb-2009 Ashish
I have been in this module to create an XML for two days and several MSXML parser have made me crazy. The code you have made is too good.

Thanks for the help you have done.
Thanks a ton 5-Feb-2009 Ashish
Too good and at least a relief for people like me, who have been in series of MSXML parsers for various problems related to XML
great guide for starters 12-Jan-2011 ddaseden
Very good guide for beginners of XML. This is a must have bookmark. I have it at http://www.delicious.com/ddasedEn
Best code I found on net 4-Mar-2011 Pooja
It is simple and self explanatory.
Home Search Contact us About us