A Simple DOM-Based XML Manager Class

Introduction

CXMLMgr is a simple XML manager class that can be used to manipulate XML files. It uses the MSXML2 namespace. You should have MSXML 4.0 SDK to use it.

Details

The interface of the class is as follows:

CXMLMgr::CXMLMgr()
Description It will initlize COM and set the default memory handler
 
CXMLMgr::~CXMLMgr()
Description           Destory & Release resources
 
HRESULT CXMLMgr::Initlize() const
Parameters None
Return HERSULT
   S_OK (on success)
   E_FAIL (on error)
Description It will initlize Document pointer
 
bool CXMLMgr::Load(LPCSTR lpcstrXMLFileName)
Parameters [in] LPCSTR
   Name & path of the .xml file to load
Return bool
   true (on success)
   false (on error)
Description It will load a valid XML document
 
HRESULT CXMLMgr::Save(LPCSTR lpcstrXMLFileName)
Parameters [in] LPCSTR
   Name & path with which the .xml file is required to be stored
Return HRESULT
   S_OK (on success)
   E_FAIL (on error)
Description Save the document to the external .xml file
 
void CXMLMgr::Release()
Parameters None
Return None
Description Release the resources
 
void CXMLMgr::Release(MSXML2::IXMLDOMDocument* pXMLDoc)
Parameters [in] MSXML2::IXMLDOMDocument*
   Document pointer
Return None
Description Release document pointer
 
void CXMLMgr::Release(MSXML2::IXMLDOMElement* pXMLElement)
Parameters [in] MSXML2::IXMLDOMElement*
   Element to release
Return None
Description Release element pointer
 
LPCSTR CXMLMgr::GetText(MSXML2::IXMLDOMNode* pElement) const
Parameters [in] MSXML2::IXMLDOMNode*
   Element which text is required
Return LPCSTR
   Text of the XML Element
Description Get the text of the node
 
LPCSTR CXMLMgr::GetNodeName(MSXML2::IXMLDOMNode* pNode) const
Parameters [in] MSXML2::IXMLDOMNode*
   Node, which name is required
Return LPCSTR
   Name of the node
Description Get the name of the node
 
LPCSTR CXMLMgr::ReturnBuffer(BSTR bstr) const
Parameters [in] BSTR
   BSTR string, which is required to be in LPCSTR
Return LPCSTR
   Output of BSTR
Description Convert BSTR string to LPCSTR and return it
 
MSXML2::IXMLDOMNode* CXMLMgr::GetFirstChild(MSXML2::IXMLDOMNode* pNode) const
Parameters [in] MSXML2::IXMLDOMNode*
   Node, which first child is required
Return MSXML2::IXMLDOMNode*
   First child of the node
Description Get the first element of the node
 
MSXML2::IXMLDOMNode* CXMLMgr::GetFirstChild() const
Parameters None
Return MSXML2::IXMLDOMNode*
   First child of the root element
Description Get the first element of the root node
 
MSXML2::IXMLDOMNode * CXMLMgr::GetLastChild(MSXML2::IXMLDOMNode * pNode) const
Parameters [in] MSXML2::IXMLDOMNode*
   Node, which last element is required
Return MSXML2::IXMLDOMNode*
   Last element of the node
Description Get the last element of the node
 
MSXML2::IXMLDOMNode * CXMLMgr::GetLastChild() const
Parameters None
Return MSXML2::IXMLDOMNode*
   Last child of the root
Description Get the last element of the root node
 
MSXML2::IXMLDOMNode * CXMLMgr::GetNextSibling(MSXML2::IXMLDOMNode* pNode) const
Parameters [in] MSXML2::IXMLDOMNode*
   Node, which sibling is required
Return MSXML2::IXMLDOMNode*
   Sibling node pointer
Description Get the next sibling of the node
 
MSXML2::IXMLDOMNodeList * CXMLMgr::GetChildList(MSXML2::IXMLDOMNode* pNode) const
Parameters [in] MSXML2::IXMLDOMNode*
   Node, which child list is required
Return MSXML2::IXMLDOMNodeList*
   Child list
Description Get the list of the child nodes contained by the node
 
const long CXMLMgr::GetNoOfChilds(MSXML2::IXMLDOMNodeList* pList) const
Parameters [in] MSXML2::IXMLDOMNodeList*
   Child node list pointer
Return long
   Number of children
Description Return the number of children of the node list
 
MSXML2::IXMLDOMNode * CXMLMgr::GetItemNode(const long lIndex, MSXML2::IXMLDOMNodeList* pList) const
Parameters [in] const long lIndex
   Index of the node in the list
[in] MSXML2::IXMLDOMNodeList*
   Pointer of the node list
Return MSXML2::IXMLDOMNode*
   Node item in the list
Description Return node, which index and child list is provided
 
LPCSTR CXMLMgr::GetItemText(MSXML2::IXMLDOMNode* pNode) const
Parameters [in] MSXML2::IXMLDOMNode*
   Node, which text is required
Return LPCSTR
   Text of the node
Description Get the text of the node
 
HRESULT CXMLMgr::CreateRoot(LPCSTR lpcstrRootName, LPCSTR lpcstrRootText)
Parameters [in] LPCSTR lpcstrRootName
   Name with which root element is required to be created
[in] LPCSTR lpcstrRootText
   Text of the root element (can be NULL)
Return HRESULT
   S_OK (on Success)
   E_FAIL (on Error)
Description Create Root element with root text. Note: If there is no text required for the root element, it can set to NULL.
 
HRESULT CXMLMgr::AppendChildToParent(MSXML2::IXMLDOMNode *pChild, MSXML2::IXMLDOMNode *pParent)
Parameters [in] MSXML2::IXMLDOMNode* pChild
   Child node to append
[in] MSXML2::IXMLDOMNode* pParent
   Parent node, to which child will be appended
Return HRESULT
   S_OK (on Success)
   E_FAIL (on Error)
Description Append one node to another
 
HRESULT CXMLMgr::InsertChild(MSXML2::IXMLDOMNode *pNewNode, MSXML2::IXMLDOMNode *pRefNode, MSXML2::IXMLDOMNode *pParentNode)
Parameters [in] MSXML2::IXMLDOMNode *pNewNode
   New node to insert
[in] MSXML2::IXMLDOMNode *pRefNode
   The address of the reference node; the newChild parameter is inserted to the left of the refChild parameter. If Null, the newChild parameter is inserted at the end of the child list.
[in] MSXML2::IXMLDOMNode *pParentNode
   Parent node, to which new child is required to be added
Return HRESULT
   S_OK (on Success)
   E_FAIL (on Error)
Description Insert new child
 
HRESULT CXMLMgr::CreateXMLFileHeader()
Parameters None
Return HRESULT
   S_OK (on Success)
   E_FAIL (on Error)
Description Create XML Header
 
HRESULT CXMLMgr::CreateComments(LPCSTR lpcstrComment)
Parameters [in] LPCSTR
   Comments
Return HRESULT
   S_OK (on Success)
   E_FAIL (on Error)
Description Write particular comments to document
 
HRESULT CXMLMgr::CreateElement(LPCSTR lpcstrElementName, LPCSTR lpcstrElementText, MSXML2::IXMLDOMNode* pParentNode, bool bAdd, int nLevel)
Parameters [in] LPCSTR lpcstrElementName
   Name of the element to be created
[in] LPCSTR lpcstrElementText
   Text of the element to be created (Can be NULL)
[in] MSXML2::IXMLDOMNode*
   Parent Node, to which the new element is required to be added
[in] bool
   true (to immediately add the element to the parent)
   false (just create the element, but don't add now)
[in] int
   Indentation level
Return HRESULT
   S_OK (on Success)
   E_FAIL (on Error)
Description Create a new element and add to the parent node (if required)
 
void CXMLMgr::AddWhiteSpaceToNode(MSXML2::IXMLDOMDocument* pDOMDoc, BSTR bstrWs, MSXML2::IXMLDOMNode* pNode)
Parameters [in] MSXML2::IXMLDOMDocument* pDOMDoc
   Document pointer
[in] BSTR bstrWs
   White space BSTR
[in] MSXML2::IXMLDOMNode* pNode
   Node to which white space is required to be created
Return None
Description Create white spaces
 
MSXML2::IXMLDOMElement* CXMLMgr::CreateNode(LPCSTR lpcstrRootName, MSXML2::IXMLDOMElement* pNode )
Parameters [in] LPCSTR
   A string specifying the name for the new element node
[in] MSXML2::IXMLDOMElement*
   The IXMLDOMElement interface for the new element
Return MSXML2::IXMLDOMElement*
   New element created
Description Creates an element node using the specified name
 
HRESULT CXMLMgr::SetNodeText(LPCSTR lpcstrText, MSXML2::IXMLDOMElement* pNode)
Parameters [in] LPCSTR
   Node text to set
[in] MSXML2::IXMLDOMElement*
   Node, which text is required to be set
Return HRESULT
   S_OK (on Success)
   E_FAIL (on Error)
Description Set the text of the specified node
 
void CXMLMgr::SetIndentLevel(int nLevel, MSXML2::IXMLDOMNode* pParentNode)
Parameters [in] int
   Indend level
[in] MSXML2::IXMLDOMNode*
   Node, which indent level is required to be set
Return None
 
HRESULT CXMLMgr::ReplaceElement(MSXML2::IXMLDOMElement* pNewElement, MSXML2::IXMLDOMElement* pOldElement, MSXML2::IXMLDOMNode* pParent)
Parameters [in] MSXML2::IXMLDOMElement* pNewElement
   New element
[in] MSXML2::IXMLDOMElement* pOldElement
   Element to be replaced
[in] MSXML2::IXMLDOMNode* pParent
   Parent which contains the element that is required to be replaced
Return HRESULT
   S_OK (on Success)
   E_FAIL (on Error)
Description Replace an existing element with the new element.
 
HRESULT CXMLMgr::RemoveElement(MSXML2::IXMLDOMElement* pElementToRemove, MSXML2::IXMLDOMNode* pParent)
Parameters [in] MSXML2::IXMLDOMElement* pElementToRemove
   Element to be removed
[in] MSXML2::IXMLDOMNode* pParent
   Parent that contains the element, required to be removed
Return HRESULT
   S_OK (on Success)
   E_FAIL (on Error)
Description Remove specified element from the parent node
 
HRESULT CXMLMgr::RemoveElement(MSXML2::IXMLDOMElement* pElementToRemove)
Parameters [in] MSXML2::IXMLDOMElement*
   Element to be removed. It will determine its parent itself
Return HRESULT
   S_OK (on Success)
   E_FAIL (on Error)
Description Remove a specified element
 
MSXML2::IXMLDOMNode* CXMLMgr::GetParent(MSXML2::IXMLDOMElement* pElement) const
Parameters [in] MSXML2::IXMLDOMElement*
   Element to which parent is required
Return MSXML2::IXMLDOMNode*
   Parent of the element
Description Return the parent of the specified element
 
MSXML2::IXMLDOMNode* CXMLMgr::GetChild(const long lIndex, MSXML2::IXMLDOMNodeList* pList) const
Parameters [in] const long lIndex
   Index of the child to get
[in] MSXML2::IXMLDOMNodeList*
   Parent list, that contains the child
Return MSXML2::IXMLDOMNode*
   child pointer
Description Get the child element from a parent list, which index is specified.
 
void CXMLMgr::Destroy()
Parameters None
Return None
Description Release resources

A Simple DOM-Based XML Manager Class

How to Use It

Simply create an object of CXMLMgr and use the different combinations of the public interface methods to achieve what you want. A few samples are as follows:

The XML file structure for the following example is as shown here (I assume it is placed at c:\\test.xml):

<?xml version="1.0"?>
<Info>
   <Info1>
      Data 1
   </Info1>

   <Info2>
      Data 2
   </Info2>

   <Info3>
      Data 3
   </Info3>

   <Info4>
      Data 4
   </Info4>

   <Info5>
      Data 5
   </Info5>
</Info>

Now, try the following code snippet. It will iterate and display each node with text in a message box.

std::string strNodeName;

CXMLMgr xmlMgr;
xmlMgr.Initlize();
xmlMgr.Load("c:\\test.xml");

for ( MSXML2::IXMLDOMNode* pNode = xmlMgr.GetFirstChild();
pNode != NULL;
pNode = xmlMgr.GetNextSibling(pNode) )
{
   strNodeName = xmlMgr.GetNodeName(pNode);
   strNodeName +=" -> ";
   strNodeName += xmlMgr.GetText(pNode);

   ::MessageBox(NULL , strNodeName.c_str() , "XML Test" , MB_OK);
}

Now, let's modify the code a little and use it with a different .xml file structure. For the following code snippet, the .xml file structure is as follows:

<?xml version="1.0"?>
<Info>
   <Data>
      <Info1>
         Data 1
      </Info1>

      <Info2>
         Data 2
      </Info2>

      <Info3>
         Data 3
      </Info3>

      <Info4>
         Data 4
      </Info4>

      <Info5>
         Data 5
      </Info5>
   </Data>
</Info>

and the code to read the file is as this:

CXMLMgr xmlMgr;
xmlMgr.Initlize();
xmlMgr.Load("c:\\test.xml");    // asuming that the above .xml file
                                // strucuture is stored in
                                // c:\test.xml

MSXML2::IXMLDOMNode* pLevel1 = xmlMgr.GetFirstChild();
for ( MSXML2::IXMLDOMNode* pNode = xmlMgr.GetFirstChild(pLevel1);
pNode != NULL;
pNode = xmlMgr.GetNextSibling(pNode) )
{
   strNodeName = xmlMgr.GetNodeName(pNode);
   strNodeName +=" -> ";
   strNodeName += xmlMgr.GetText(pNode);

   ::MessageBox(NULL , strNodeName.c_str() , "XML Test" , MB_OK);
}

It isn't much different from the first one, is it? Okay, now try this:

CXMLMgr xmlMgr;
xmlMgr.Initlize();
xmlMgr.CreateXMLFileHeader();
xmlMgr.CreateRoot("Info");

MSXML2::IXMLDOMElement* pElem = xmlMgr.GetRoot();
xmlMgr.CreateElement("Data" , NULL , pElem);
pElem = xmlMgr.GetLastItemAdded();

   xmlMgr.CreateElement("Node1" , "Text1" , pElem);
   xmlMgr.CreateElement("Node2" , "Text2" , pElem);
   xmlMgr.CreateElement("Node3" , "Text3" , pElem);
   xmlMgr.CreateElement("Node4" , "Text4" , pElem);
   xmlMgr.CreateElement("Node5" , "Text5" , pElem);

xmlMgr.Save("c:\\test.xml");

This will save the above strucuture in c:\test.xml file. Similarly, you can use the following code to add an element in the .xml document.

CXMLMgr xmlMgr;
xmlMgr.Initlize();
xmlMgr.Load("c:\\test.xml");


MSXML2::IXMLDOMElement* pRoot = xmlMgr.GetRoot();
MSXML2::IXMLDOMNode* pNodePlace = NULL;    // To add the node at
                                           // the last

// MSXML2::IXMLDOMNode* pNodePlace = xmlMgr.GetFirstChild();
// MSXML2::IXMLDOMNode* pNodePlace = xmlMgr.GetLastChild();

if (S_OK == xmlMgr.CreateElement( "NewNode" ,NULL ,pRoot ,
                                  false ,1 ))
{
   // Element Node has been created, now set the sub nodes in it
   MSXML2::IXMLDOMElement *pElement = xmlMgr.GetLastItemAdded();

   xmlMgr.CreateElement( "SubNode1" , "Sub Node 1" , pElement ,
                         true , 2);
   xmlMgr.CreateElement( "SubNode2" , "Sub Node 2" , pElement ,
                         true , 2);
   xmlMgr.CreateElement( "SubNode3" , "Sub Node 3" , pElement ,
                         true , 2);

   // Now add the element in the XMLDOM
   xmlMgr.InsertChild(pElement , pNodePlace);

   // Save the DOM to file
   xmlMgr.Save("c:\\test.xml");
}

The rest is up to you. You can use other combinations to achieve what you want. Have fun.



Downloads

Comments

  • There are no comments yet. Be the first to comment!

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Hybrid cloud platforms need to think in terms of sweet spots when it comes to application platform interface (API) integration. Cloud Velocity has taken a unique approach to tight integration with the API sweet spot; enough to support the agility of physical and virtual apps, including multi-tier environments and databases, while reducing capital and operating costs. Read this case study to learn how a global-level Fortune 1000 company was able to deploy an entire 6+ TB Oracle eCommerce stack in Amazon Web …

  • Is your sales and operations planning helping or hurting your bottom line? Here are 5 useful tips from the experts at Quintiq to guide you to a better S&OP strategy.

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds