How to create an XML file

22 01 2012

In one of the previous posts we have seen how to read an XML file, similar way sometimes we may need to create an XML file from our applications.

To read and write and XML file Microsoft provides an XML parser know as MSXML. This is a COM component that comes with different MS Products like MS Windows, MS IEs, MS Office etc.

XMLDomWriter.h

XMLDomWriter.cpp

 

 

#include "XMLDomWriter.h"

void CreateXMLFile()
{
	CXMLNode		rootNode;
	CXMLDomDocument doc;

	rootNode = doc.CreateRootNode( _T("RootNode"));
	rootNode.AddNewLine();
	CXMLNode firstNode(doc.CreateNode(_T("Node1")));
	rootNode.AppendNode( firstNode );
	firstNode.AddNewLine();
	firstNode.SetAttributes( _T("AttributeName"), _T("AttributeValue"));
	CXMLNode childNode(doc.CreateNode(_T("ChildNode")));
	childNode.SetValue(_T("NodeValue"));
	firstNode.AddChildNode( childNode );
	firstNode.AddNewLine();
	rootNode.AddNewLine();

	doc.Save("c:\\test.xml");
}

Please download the attached XMLDomWriter.h and XMLDOMWriter.cpp files and include it into your project. You may need to change the msxml dll import section of header file as per the compiler version.





How to read an XML file

7 01 2012

XML – eXtensible Markup Language allows data to be stored in a particular format. Nowadays most of the applications use XML format to store the application and profile information. So as a programmer we can just check how to read the contents(nodes, attributes etc) of an XML file.

To read and write and XML file Microsoft provides an XML parser know as MSXML. This is a COM component that comes with different MS Products like MS Windows, MS IEs, MS Office etc.

See the following sample code.


XMLDomParser.h

#pragma once

#include 

/* change it as per OS/VS verion*/
#import  raw_interfaces_only
using namespace MSXML2;

/***************** CXMLDomDocument ***************/

class CXMLDomDocument
{

public: /** Public constructor/destructor */

    /** Constructor. */
    CXMLDomDocument(void);

    /** Destructor. */
    ~CXMLDomDocument(void);

public: 

    /** Initialize MS XML Domparser */
    BOOL InitMSXML();

    /** Check the validity of xml pointer. */
    BOOL IsValid() const;

    /** Load an xml file. */
    BOOL LoadXMLFile(/*[in]*/ const CString& filename );

    /** Load an xml string. */
    BOOL LoadXML(LPCTSTR xml);

    /** Get the child node list. */
    MSXML2::IXMLDOMNodeListPtr GetChildNodesList();

private:

    // Holds the xml dom pointer.
    MSXML2::IXMLDOMDocumentPtr m_xmldocPtr;
};

/***************** CXMLNodeList ***************/

class CXMLNodeList
{

public: /** Public constructor/destructor */

    /** Constructor. */
	CXMLNodeList();

    /** Parameterized Constructor. */
    CXMLNodeList(MSXML2::IXMLDOMNodeListPtr pList);

    /** Destructor. */
	~CXMLNodeList();

public:

    /** Get total number of child nodes. */
	int Count();

    /** Check the validity of the node list. */
    BOOL IsValid() const;

    /** Get the next node from the list. */
    MSXML2::IXMLDOMNodePtr Next();

    /** Get a node by index. */
    MSXML2::IXMLDOMNodePtr Node(/*[in]*/ int index);

private:

    // Holds the node list pointer.
	MSXML2::IXMLDOMNodeListPtr m_xmlnodelist;

};

/***************** CXMLNode ***************/

class CXMLNode
{

public: /** Public constructor/destructor */

    /** Constructor. */
	CXMLNode();

     /** Parameterized Constructor. */
	CXMLNode(/*[in]*/ MSXML2::IXMLDOMNodePtr pNode);

    /** Destructor. */
	~CXMLNode();

public:

    /** Check the validity of a node. */
	BOOL IsValid() const;

    /** Get the node name. */
	CString GetNodeName();

    /** Check whether thr node has child node or not. */
	BOOL HasChildNodes();

    /** Get the number of attributes of a node. */
	long GetAttributesCount();

    /** Get the attribute value. */
	CString GetAttributeValue(/*[in]*/ int index) const;

    /** Get the attribute name. */
    CString GetAttributeName(/*[in]*/ int index) const;

    /** Get the child nodes. */
	MSXML2::IXMLDOMNodeListPtr GetChildNodes();

    /** Get a node by index. */
    MSXML2::IXMLDOMNodePtr GetNode(/*[in]*/ int nodeIndex);

    /** Get a node by name. */
    MSXML2::IXMLDOMNodePtr GetNode(/*[in]*/ LPCTSTR nodeName);

private:

    // Holds the xml node pointer
	MSXML2::IXMLDOMNodePtr m_xmlnode;

};

XMLDomParser.cpp

#include "StdAfx.h"
#include "XMLDomParser.h"

void LogComError(_com_error &e)
{
    _bstr_t bstrDescription(e.Description());
    CString strErrorMsg;
    strErrorMsg.Format(_T("%s"), (LPCTSTR)bstrDescription);

    AfxMessageBox(strErrorMsg);
}

/***************** CXMLDomDocument ***************/

CXMLDomDocument::CXMLDomDocument(void) :
m_xmldocPtr(NULL)
{
    CoInitialize( NULL );
}

CXMLDomDocument::~CXMLDomDocument(void)
{
    CoUninitialize();
}

BOOL CXMLDomDocument::InitMSXML()
{
    HRESULT hr = m_xmldocPtr.CreateInstance(CLSID_DOMDocument);
    if (SUCCEEDED(hr))
    {
        return TRUE;
    }
    return FALSE;
}

BOOL CXMLDomDocument::IsValid() const
{
	if (NULL == m_xmldocPtr)
		return FALSE;

    if (NULL == m_xmldocPtr.GetInterfacePtr())
		return FALSE;

    return TRUE;
}

BOOL CXMLDomDocument::LoadXMLFile( /*[in]*/ const CString& filename )
{
   try
   {
      _variant_t varXml(filename);
      VARIANT_BOOL bTrue = FALSE;
      HRESULT hr;
      m_xmldocPtr->put_async(VARIANT_FALSE);

      if ((hr = m_xmldocPtr->load(varXml,&bTrue)) != S_OK)
      {
         return FALSE;
      }

      return TRUE;
   }
   catch (_com_error &e)
   {
       LogComError( e );
   }

   return FALSE;
}

BOOL CXMLDomDocument::LoadXML(/*[in]*/ LPCTSTR xml)
{
    if (!IsValid())
        return FALSE;

    HRESULT hr;

    VARIANT_BOOL bTrue = FALSE;

    if ((hr = m_xmldocPtr->loadXML((BSTR)xml,&bTrue)) != S_OK)
    {
        AfxMessageBox("LoadXML failed");
        return FALSE;
    }

    return TRUE;
}

MSXML2::IXMLDOMNodeListPtr CXMLDomDocument::GetChildNodesList()
{
   HRESULT hr;
   MSXML2::IXMLDOMNodeListPtr XmlNodeListPtr = NULL;

   if ((hr = m_xmldocPtr->get_childNodes(&XmlNodeListPtr)) != S_OK)
   {
       AfxMessageBox("Failed to get child nodes from xml file.");
   }

   return XmlNodeListPtr;
}

/***************** CXMLNodeList ***************/

CXMLNodeList::CXMLNodeList()
{
}

CXMLNodeList::CXMLNodeList(MSXML2::IXMLDOMNodeListPtr pList) :
m_xmlnodelist(pList)
{
}

CXMLNodeList::~CXMLNodeList()
{
}

int CXMLNodeList::Count()
{
    long cnt = 0;

    if (IsValid())
        m_xmlnodelist->get_length(&cnt);

    return cnt;
}

BOOL CXMLNodeList::IsValid() const
{
    if (NULL == m_xmlnodelist)
        return FALSE;
    if (NULL == m_xmlnodelist.GetInterfacePtr())
        return FALSE;

    return TRUE;
}

MSXML2::IXMLDOMNodePtr CXMLNodeList::Next()
{
    MSXML2::IXMLDOMNodePtr NodePtr = NULL;
    if (IsValid())
    {
        m_xmlnodelist->nextNode(&NodePtr);
    }

    return NodePtr;
}

MSXML2::IXMLDOMNodePtr CXMLNodeList::Node(/*[in]*/ int index)
{
    MSXML2::IXMLDOMNodePtr NodePtr = NULL;
    if (IsValid())
        m_xmlnodelist->get_item(index,&NodePtr);

    return NodePtr;
}

/***************** CXMLNode ***************/

CXMLNode::CXMLNode()
{
}

CXMLNode::CXMLNode(MSXML2::IXMLDOMNodePtr pNode) :
m_xmlnode(pNode)
{
}

CXMLNode::~CXMLNode()
{
}

BOOL CXMLNode::IsValid() const
{
    if (NULL == m_xmlnode)
        return FALSE;
    if (NULL == m_xmlnode.GetInterfacePtr())
        return FALSE;

    return TRUE;
}

CString CXMLNode::GetNodeName()
{
    BSTR v;
    m_xmlnode->get_nodeName(&v);
    return (CString)v;
}

long CXMLNode::GetAttributesCount()
{

    long ret = 0;
    if(IsValid())
    {
        MSXML2::IXMLDOMNamedNodeMapPtr attribs = NULL;
        if( S_OK == m_xmlnode->get_attributes(&attribs))
            attribs->get_length(&ret);
    }
    return ret;
}

CString CXMLNode::GetAttributeName(/*[in]*/ int index) const
{

    BSTR ret(L"");
    if(IsValid())
    {
        MSXML2::IXMLDOMNamedNodeMapPtr attribs = NULL;
        if (S_OK == m_xmlnode->get_attributes(&attribs))
        {
            MSXML2::IXMLDOMNodePtr attrib = NULL;
            if(S_OK == attribs->get_item(index,&attrib))
                attrib->get_nodeName(&ret);
        }
    }

    return (CString)ret;
}

CString CXMLNode::GetAttributeValue(/*[in]*/ int index) const
{

    BSTR ret(L"");
    if(IsValid())
    {
        MSXML2::IXMLDOMNamedNodeMapPtr attribs = NULL;
        if (S_OK == m_xmlnode->get_attributes(&attribs))
        {
            MSXML2::IXMLDOMNodePtr attrib = NULL;
            if(S_OK == attribs->get_item(index,&attrib))
                attrib->get_text(&ret);
        }
    }
    return (CString)ret;
}

BOOL CXMLNode::HasChildNodes()
{
    VARIANT_BOOL ret = FALSE;
    if(IsValid())
        m_xmlnode->hasChildNodes(&ret);
    return ret;

}

MSXML2::IXMLDOMNodeListPtr CXMLNode::GetChildNodes()
{
    MSXML2::IXMLDOMNodeListPtr SubNodeList = NULL;
    if(IsValid())
        m_xmlnode->get_childNodes(&SubNodeList);
    return SubNodeList;
}

MSXML2::IXMLDOMNodePtr CXMLNode::GetNode(/*[in]*/ LPCTSTR nodeName)
{
    MSXML2::IXMLDOMNodePtr NodePtr = NULL;

    try
    {
        if(IsValid())
            m_xmlnode->selectSingleNode((BSTR)nodeName,&NodePtr);
    }
    catch (_com_error e)
    {
        LogComError( e );
    }

    return NodePtr;
}

MSXML2::IXMLDOMNodePtr CXMLNode::GetNode(/*[in]*/ int nodeIndex)
{
    MSXML2::IXMLDOMNodeListPtr NodeListPtr = NULL;
    MSXML2::IXMLDOMNodePtr  NodePtr = NULL;

    if (IsValid())
    {
        if(m_xmlnode->get_childNodes(&NodeListPtr) == S_OK)
            NodeListPtr->get_item(nodeIndex,&NodePtr);
    }

    return NodePtr;
}

XML Dom Parser Test Code

/** XML Dom Parser implementation class */
#include "XMLDomParser.h"

BOOL CXMLReaderDlg::ReadXMLFile(CString& p_strFilePath)
{
CXMLDomDocument xmlDomDoc;

if (!xmlDomDoc.InitMSXML())
{
return FALSE;
}

if (!xmlDomDoc.LoadXMLFile(p_strFilePath) || !xmlDomDoc.IsValid())
{
return FALSE;
}

CXMLNodeList mainNodeList = xmlDomDoc.GetChildNodesList();

int nMainNodecount = mainNodeList.Count();

/** Read the nodes */
for (int nCount = 0; nCount < nMainNodecount; nCount++)
{
CXMLNode subNode(mainNodeList.Next());

if (!subNode.IsValid())
{
return FALSE;
}

CString strNodeName = subNode.GetNodeName();

int nAttributeCount = subNode.GetAttributesCount();
CString strAttrName, strAttrValue;

/** Read the attributes */
for (int nIndex = 0; nIndex < nAttributeCount; nIndex++)
{
strAttrName = subNode.GetAttributeName(nIndex);
strAttrValue = subNode.GetAttributeValue(nIndex);
}
}

return TRUE;
}

Please save the code snippet of XMLDomParser.h and XMLDOMParser.cpp into different files and include it into your project. You may need to change the msxml dll import section of header file as per the compiler version.