Click here to Skip to main content
15,867,594 members
Articles / Desktop Programming / MFC
Article

C++ XML the easy way!

Rate me:
Please Sign up or sign in to vote.
4.93/5 (68 votes)
10 Jun 2005CPOL5 min read 1.2M   12.4K   143   225
A wrapper for the XML DOM for C++.

Introduction

This article is a successor to my previous article Wrapper class for IXMLDDOMDocument.

The reason that it's published as a different article and not an update is that, it's in no way compatible with the previous one. There are different classes and functions. Also the main difference is that this wrapper works directly with XML pointers without first parsing the XML tree, which leads to a significant speed improvement.

Usage

Add the file "XmlNodeWrapper.cpp" to your project's source files.

Include the file "XmlNodeWrapper.h" in the files you would like to use the wrapper.

#include "XmlNodeWrapper.h"

Reference

CXmlDocumentWrapper

Constructors
  • CXmlDocumentWrapper()

    Creates a new instance of XML document. You have to load a document via Load() or LoadXml()

  • CXmlDocumentWrapper(IXMLDOMDocumentPtr pDoc)

    Attaches the wrapper to the existing document pointer. Will accept as input an IXMLDOMDocumentPtr, IXMLDOMDocument* pointer or IDispatch* pointer.

Methods
  • BOOL IsValid()

    Returns TRUE if the wrapper has a valid pointer to XML document.

  • MSXML2::IXMLDOMDocument* Detach()

    Detaches the wrapper from the XML pointer and returns the pointer. Useful if you passed the external pointer in the constructor and would not like to decrease the reference count on the pointer.

  • MSXML2::IXMLDOMDocument* Clone()

    Creates and returns a clone of the document.

    Suggested usage:

    CXmlDocumentWrapper newDoc(sourceDoc.Clone());
  • BOOL Load(LPCTSTR path)

    Loads a document from a disk file. Returns TRUE on success.

    Usage:

    CXmlDocumentWrapper doc;
    doc.Load("C:\\Test\\xmlSource.xml");
  • BOOL LoadXML(LPCTSTR xml)

    Load the document from a string. Returns TRUE on success.

    Usage:

    CXmlDocumentWrapper doc;
    doc.LoadXML("<Root><SomeObject></SomeObject></Root>");
  • BOOL Save(LPCTSTR path = "")

    Saves the document to a disk file. If the path is an empty string or omitted, the current document URL is used.

  • MSXML2::IXMLDOMNode* AsNode()

    Returns the document root element as XML node.

    Usage:

    CXmlNodeWrapper xmlNode(xmlDoc.AsNode());
  • CString GetXML()

    Returns the current XML loaded in the document as a CString.

  • CString GetUrl()

    Returns the current document URL. Note: The URL is updated every time you use Load() or Save() functions.

CXmlNodeWrapper

Constructors
  • CXmlNodeWrapper()

    Creates an empty Node wrapper. You have to use operator = or Attach() on this node.

  • CXmlNodeWrapper(MSXML2::IXMLDOMNodePtr pNode,BOOL bAutoRelease = TRUE)

    Creates a wrapper from XMl pointer to existing XML node. Will accept IXMLDOMNodePtr, IXMLDOMNode* or IDispatch* pointer. If the bAutoRelease parameter is FALSE, Detach() will be called in the destructor.

  • void operator=(MSXML2::IXMLDOMNodePtr pNode)

    Same as the above.

Methods
  • BOOL IsValid()

    Returns TRUE if the XML pointer in the wrapper is valid.

  • void SetValue(LPCTSTR valueName,LPCTSTR value)
  • void SetValue(LPCTSTR valueName,int value)
  • void SetValue(LPCTSTR valueName,short value)
  • void SetValue(LPCTSTR valueName,double value)
  • void SetValue(LPCTSTR valueName,float value)
  • void SetValue(LPCTSTR valueName,bool value)

    Sets a value for an attribute. If the attribute exists it's value is updated, otherwise a new attribute will be created.

  • CString GetValue(LPCTSTR valueName)

    Returns a value of an attribute as a CString. If the attribute does not exists, an empty string will be returned.

  • MSXML2::IXMLDOMNode* GetPrevSibling()
  • MSXML2::IXMLDOMNode* GetNextSibling()

    Gets the next or previous sibling of this node. If no such exists NULL will be returned.

    Usage:

    CXmlNodeWrapper prevNode(theNode.GetPrevSibling());
    CXmlNodeWrapper nextNode(theNode.GetNextSibling());
    if (prevNode.IsValid())
    {
          // Do things
    }
    else if (nextNode.IsValid())
    {
         // Do things
    }
  • MSXML2::IXMLDOMNode* GetNode(LPCTSTR nodeName)
  • MSXML2::IXMLDOMNode* GetNode(int nodeIndex)

    Returns a child node of this node by index or by name. If no node is found, NULL will be returned. When searching by name only the first matching node will be returned.

    Usage:

    CXmlNodeWrapper childNode(theNode.GetNode(0));
    if (!childNode.IsValid())
    {
         childNode = theNode.GetNode("MyChild");
         // Do things
    }
  • MSXML2::IXMLDOMNode* FindNode(LPCTSTR searchString)

    Returns a single node by evaluating an XSL search pattern (A wrapper for selectSingleNode function).

    Usage:

    //Finds the node with the name "Object"
    // who's "Type" attribute equals "Simple":
    CXmlNodeWrapper resultNode(
                 theNode.FindNode("//Object[@Type='Simple']"));
  • MSXML2::IXMLDOMNodeList* FindNodes(LPCTSTR searchStr)

    Returns a list of nodes by evaluating an XSL search pattern (A wrapper for selectNodes function).

    Usage:

    //Finds all the nodes with the name "Object" 
    //who's "Type" attribute equals "Simple":
    CXmlNodeListWrapper nodeList(
           theNode.FindNodes("//Object[@Type='Simple']"));
  • long NumNodes()

    Returns the number of child nodes.

  • MSXML2::IXMLDOMNode* Parent()

    Return a parent node of this node or NULL if none.

    Usage:

    CXmlNodeWrapper parentNode(theNode.Parent());
  • CString Name();

    Returns the name of the node.

  • CString GetText()

    Returns the text contents of the node.

  • void SetText(LPCTSTR text)

    Sets the text contents of the node.

  • MSXML2::IXMLDOMDocument* ParentDocument()

    Returns the document that this node belongs to or NULL if not applicable.

    Usage:

    CXmlDocumentWrapper xmlDoc(theNode.ParentDocument());
  • MSXML2::IXMLDOMNode* Interface()

    Returns the raw interface pointer, useful to invoke some of the methods not provided by the wrapper or to pass the interface to some other functions without detaching from the wrapper.

  • MSXML2::IXMLDOMNode* Detach()

    Detaches from the XML pointer without calling Release() on it and returns the pointer.

  • CString GetXML()

    Returns the XML contents of the node as CString.

  • MSXML2::IXMLDOMNode* InsertNode(int index,LPCTSTR nodeName)

    Creates a new XML node with the given name and inserts it as a child of this node. Use index=0 to insert as a first child and index=NumNodes() to insert as the last. Returns a pointer to the new node.

    Usage:

    CXmlNodeWrapper newChild(
            theNode.InsertNode(theNode.NumNodes(),"MyNewChild");
    newChild.SetValue("SomeValue","Undefined");
  • MSXML2::IXMLDOMNode* InsertNode(int index,MSXML2::IXMLDOMNodePtr pNode)

    Same as above. Only the new child is not created but accepts a pre-existing pointer to a node.

    Usage:

    // Create a copy of a document 
    //and insert as a child into existing node
    CXmlDocumentWrapper doc;
    doc.Load("C:\\Temp\\xmlSource.xml);
    CXmlNodeWrapper sourceNode(doc.AsNode());
    CXmlDocumentWrapper cloneDoc(doc.Clone());
    sourceNode.InsertNode(0,cloneDoc.AsNode());
  • MSXML2::IXMLDOMNode* InsertAfter(MSXML2::IXMLDOMNode* refNode, LPCTSTR nodeName)
  • MSXML2::IXMLDOMNode* InsertBefore(MSXML2::IXMLDOMNode* refNode, LPCTSTR nodeName)

    Create and insert a new child node with the given name before or after the referenced node. Returns the newly created node.

  • MSXML2::IXMLDOMNode* InsertAfter(MSXML2::IXMLDOMNode *refNode, MSXML2::IXMLDOMNode *pNode)

    Insert an existing node after the referenced node. Returns the inserted node.

  • MSXML2::IXMLDOMNode* RemoveNode(MSXML2::IXMLDOMNodePtr pNode)

    Removes the specified node from the child list of this node. Returns a pointer to the removed node.

  • void RemoveNodes(LPCTSTR searchStr)

    Removes nodes from the child list of this node by evaluating XSL pattern. See FindNodes for an example.

  • void ReplaceNode(MSXML2::IXMLDOMNode* pOldNode,MSXML2::IXMLDOMNode* pNewNode)

    Replaces an existing child node with a new node.

CXmlNodeListWrapper

Constructors
  • CXmlNodeListWrapper()

    Creates an empty node list wrapper, you have to use the operator = to initialize it.

  • CXmlNodeListWrapper(MSXML2::IXMLDOMNodeListPtr pList)

    Creates a node list from an existing IXMLDOMNodeList pointer, will accept IXMLDOMNodeListPtr, IXMLDOMNodeList* pointer or IDispatch* pointer. See example in CXmlNodeWrapper::FindNodes().

  • void operator=(MSXML2::IXMLDOMNodeListPtr pList)

    Same as above.

Methods
  • BOOL IsValid()

    Returns TRUE if the list pointer is valid.

  • int Count()

    Returns the number of nodes in the list.

  • MSXML2::IXMLDOMNode* Node(int index)

    Return the nth node in the list.

    Usage:

    for (int i = 0; i < nodeList.Count(); i++)
    {
         CXmlNodeWrapper node(nodeList.Node(i));
         // Do things
    }
  • void Start()

    Resets the iterator. See example in Next().

  • MSXML2::IXMLDOMNode* Next()

    Return the next node in the list when iterating or NULL if none.

    Usage:

    nodeList.Start();
    CXmlNodeWrapper node(nodeList.Next());
    while (node.IsValid())
    {
        // Do things
        node = nodeList.Next();
    }
  • MSXML2::IXMLDOMDocument* AsDocument()

    Converts the node list to a new document in the form: <NodeList>THENODES</NodeList>

    Usage:

    CXmlDocumentWrapper doc(theList.AsDocument());

Update

The sample is now available for download. Also a few more new functions are included:

  • int CXmlNodeWrapper::NumAttributes() - returns the number of attributes in the node.
  • CString CXmlNodeWrapper::NodeType() - returns the type of the node : "element", "text", etc.
  • CString CXmlNodeWrapper::GetAttribName(int index) - returns the name of the attribute at index.
  • CString CXmlNodeWrapper::GetAttribVal(int index) - returns the value of the attribute at index.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) RDV Systems
Israel Israel
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
Generalneed simple example to parse xml Pin
6-Jul-05 5:08
suss6-Jul-05 5:08 
GeneralRe: need simple example to parse xml Pin
Stellar Developer6-Jul-05 12:10
Stellar Developer6-Jul-05 12:10 
GeneralRe: need simple example to parse xml Pin
Alex Hazanov6-Jul-05 20:47
Alex Hazanov6-Jul-05 20:47 
QuestionReturn value? Pin
Aldus@Monitor22-Jun-05 4:17
Aldus@Monitor22-Jun-05 4:17 
GeneralLinker error Pin
Aldus@Monitor12-Jun-05 20:38
Aldus@Monitor12-Jun-05 20:38 
GeneralRe: Linker error Pin
Aldus@Monitor12-Jun-05 20:50
Aldus@Monitor12-Jun-05 20:50 
GeneralRe: Linker error Pin
Alex Hazanov13-Jun-05 20:49
Alex Hazanov13-Jun-05 20:49 
GeneralUse in a Windows Service Pin
Nandiator8-Jun-05 1:19
Nandiator8-Jun-05 1:19 
I have tested the classes to use them in my application and I have realized that they only work for Doc/View projects (at least in VS2003), not in dialog or console based apps.

In non Doc/View apps it fails in:
<br />
CXmlDocumentWrapper::CXmlDocumentWrapper()<br />
{<br />
	m_xmldoc.CreateInstance(MSXML2::CLSID_DOMDocument);<br />
}<br />

It always returns NULL.

How can I modify the classes to make them work in a Windows Service or a console app?
Is it possible or it depends on the dll?
GeneralRe: Use in a Windows Service Pin
Alex Hazanov8-Jun-05 9:37
Alex Hazanov8-Jun-05 9:37 
GeneralRe: Use in a Windows Service Pin
Nandiator29-Dec-05 23:49
Nandiator29-Dec-05 23:49 
Generalsubtle memory issue Pin
.dan.g.7-Jun-05 16:56
professional.dan.g.7-Jun-05 16:56 
GeneralRe: subtle memory issue Pin
Alex Hazanov8-Jun-05 9:36
Alex Hazanov8-Jun-05 9:36 
GeneralRe: subtle memory issue Pin
.dan.g.8-Jun-05 14:32
professional.dan.g.8-Jun-05 14:32 
GeneralRe: subtle memory issue Pin
Alex Hazanov9-Jun-05 3:46
Alex Hazanov9-Jun-05 3:46 
GeneralRe: subtle memory issue Pin
Rouslan Grabar [Russ]15-Jun-05 2:01
Rouslan Grabar [Russ]15-Jun-05 2:01 
GeneralRe: subtle memory issue Pin
maury_7327-May-10 0:30
maury_7327-May-10 0:30 
GeneralTry it by your huge file please! Pin
andré_k16-Jun-05 13:04
andré_k16-Jun-05 13:04 
GeneralRe: Try it by your huge file please! Pin
.dan.g.16-Jun-05 16:22
professional.dan.g.16-Jun-05 16:22 
GeneralReleasing Memory Pin
.dan.g.31-May-05 14:46
professional.dan.g.31-May-05 14:46 
GeneralRe: Releasing Memory Pin
Alex Hazanov31-May-05 21:02
Alex Hazanov31-May-05 21:02 
GeneralRe: Releasing Memory Pin
.dan.g.1-Jun-05 17:49
professional.dan.g.1-Jun-05 17:49 
GeneralLoad Failure @@... Pin
weilun27-May-05 4:19
weilun27-May-05 4:19 
GeneralRe: Load Failure @@... Pin
weilun27-May-05 21:52
weilun27-May-05 21:52 
GeneralRe: Load Failure @@... Pin
Snarfster13-Oct-05 11:42
Snarfster13-Oct-05 11:42 
GeneralResource Leak Pin
26-May-05 16:13
suss26-May-05 16:13 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.