XML++

Published:
Updated:
This article's goal is to present you with an easy to use XML wrapper for C++ and also present some interesting techniques that you might use with MS C++.
The reason I built this class is to ease the pain of using XML files with C++, since there is no native XML support, but only through COM it is not always trivial to untrained programmer.

First the header file for the class:
File: xml++.h
#pragma once
                      
                      #import "MSXML3.dll" named_guids 
                      #include <string>
                      
                      class xmldocument;
                      class xmlnode;
                      class xmlnodelist;
                      
                      class xmldocument
                      {
                      public:
                      	/// Constructor
                      	xmldocument()
                      	{
                      		CoInitialize(NULL);
                      		m_xmldoc.CreateInstance(MSXML2::CLSID_DOMDocument30);
                      		MSXML2::IXMLDOMDocument2Ptr doc = m_xmldoc;
                      		doc->setProperty("SelectionLanguage","XPath");
                      	}
                      
                      	/// Loading
                      	bool load(std::string url)
                      	{
                      		if (m_xmldoc!=NULL) 
                      		{
                      			_variant_t v(url.c_str());
                      			m_xmldoc->put_async(VARIANT_FALSE);
                      			VARIANT_BOOL success = m_xmldoc->load(v);
                      			return success == VARIANT_TRUE;
                      		}
                      		return false;
                      	}
                      	bool load(std::wstring url)
                      	{
                      		if (m_xmldoc!=NULL) 
                      		{
                      			_variant_t v(url.c_str());
                      			m_xmldoc->put_async(VARIANT_FALSE);
                      			VARIANT_BOOL success = m_xmldoc->load(v);
                      			return success == VARIANT_TRUE;
                      		}
                      		return false;
                      	}
                      
                      	bool save(std::string url)
                      	{
                      		_variant_t v(url.c_str());
                      		return m_xmldoc->save(v) == S_OK;
                      	}
                      	bool save(std::wstring url)
                      	{
                      		_variant_t v(url.c_str());
                      		return m_xmldoc->save(v) == S_OK;
                      	}
                      
                      	// Access operators
                      	MSXML2::IXMLDOMNodePtr operator[](int index)
                      	{
                      		if (m_xmldoc!=NULL) return  m_xmldoc->childNodes->item[index];
                      		else return NULL;
                      	}
                      	MSXML2::IXMLDOMNodePtr operator[](std::string name)
                      	{
                      		if (m_xmldoc!=NULL) return m_xmldoc->selectSingleNode(name.c_str());
                      		else return NULL;
                      	}
                      	MSXML2::IXMLDOMNodePtr operator[](std::wstring name)
                      	{
                      		if (m_xmldoc!=NULL) return m_xmldoc->selectSingleNode(name.c_str());
                      		else return NULL;
                      	}
                      
                      	MSXML2::IXMLDOMNodeListPtr operator()(std::string xpath)
                      	{
                      		if (m_xmldoc!=NULL) return m_xmldoc->selectNodes(xpath.c_str());
                      		else return NULL;
                      	}
                      	MSXML2::IXMLDOMNodeListPtr operator()(std::wstring xpath)
                      	{
                      		if (m_xmldoc!=NULL) return m_xmldoc->selectNodes(xpath.c_str());
                      		else return NULL;
                      	}
                      
                      	MSXML2::IXMLDOMNodeListPtr children()
                      	{
                      		if (m_xmldoc!=NULL) return m_xmldoc->childNodes;
                      		else return NULL;
                      	}
                      
                      	/// Cast operators / extractors
                      	operator MSXML2::IXMLDOMNodePtr()
                      	{
                      		if (m_xmldoc!=NULL) return m_xmldoc->documentElement;
                      		else return NULL;
                      	}
                      
                      private:
                      	MSXML2::IXMLDOMDocumentPtr m_xmldoc;
                      };
                      
                      class xmlnode
                      {
                      public:
                      	struct xmlvalue
                      	{
                      		_bstr_t value;
                      		xmlvalue() {}
                      		xmlvalue(_bstr_t val) { value = val; }
                      		
                      		operator std::string()
                      		{
                      			return (const char*)value;
                      		}
                      		operator std::wstring()
                      		{
                      			return (const wchar_t*)value;
                      		}
                      
                      		operator bool()
                      		{
                      			
                      			if (_stricmp(value, "yes") == 0 || _stricmp(value, "true") == 0 || _stricmp(value, "1") == 0)
                      				return true;
                      			else return false;			
                      			return false;
                      		}
                      		operator short()
                      		{
                      			return atoi(value);
                      		}
                      		operator int()
                      		{
                      			return atoi(value);
                      		}
                      		operator long()
                      		{
                      			return atol(value);
                      		}
                      		operator unsigned short()
                      		{
                      			return atoi(value);
                      		}
                      		operator unsigned long()
                      		{
                      			return atol(value);
                      		}
                      		operator float()
                      		{
                      			return (float)atof(value);
                      		}
                      		operator double()
                      		{
                      			return atof(value);
                      		}
                      	};
                      public:
                      	xmlnode(MSXML2::IXMLDOMNodePtr source)
                      	{
                      		m_xmlnode = source;
                      	}	
                      	void operator=(MSXML2::IXMLDOMNodePtr source)
                      	{
                      			m_xmlnode = source;
                      	}
                      
                      	xmlnode operator[](int index)
                      	{
                      		if (m_xmlnode!=NULL) return  m_xmlnode->childNodes->item[index];
                      		else return NULL;
                      	}
                      	xmlnode operator[](std::string name)
                      	{
                      		if (m_xmlnode!=NULL) return m_xmlnode->selectSingleNode(name.c_str());
                      		else return NULL;
                      	}
                      	xmlnode operator[](std::wstring name)
                      	{
                      		if (m_xmlnode!=NULL) return m_xmlnode->selectSingleNode(name.c_str());
                      		else return NULL;
                      	}
                      
                      	MSXML2::IXMLDOMNodeListPtr operator()(std::string xpath)
                      	{
                      		if (m_xmlnode!=NULL) return m_xmlnode->selectNodes(xpath.c_str());
                      		else return NULL;
                      	}
                      	MSXML2::IXMLDOMNodeListPtr operator()(std::wstring xpath)
                      	{
                      		if (m_xmlnode!=NULL) return m_xmlnode->selectNodes(xpath.c_str());
                      		else return NULL;
                      	}
                      
                      
                      	__declspec(property(get=Getvalue,put=Putvalue))
                      		xmlvalue value;
                      	xmlvalue Getvalue()
                      	{
                      		if (m_xmlnode!=NULL) return xmlvalue(m_xmlnode->text);
                      		return xmlvalue();
                      	}
                      	void Putvalue(xmlvalue newVal)
                      	{
                      		if (m_xmlnode!=NULL) m_xmlnode->text = newVal.value;
                      	}
                      
                      
                      	
                      private:
                      	MSXML2::IXMLDOMNodePtr m_xmlnode;
                      };
                      
                      class xmlnodelist
                      {
                      public:
                      	xmlnodelist(MSXML2::IXMLDOMNodeListPtr source)
                      	{
                      		m_xmlnodelist = source;
                      	}
                      	void operator=(MSXML2::IXMLDOMNodeListPtr source)
                      	{
                      		m_xmlnodelist = source;
                      	}
                      
                      	int length()
                      	{
                      		if (m_xmlnodelist!=NULL) return m_xmlnodelist->length;
                      		else return 0;
                      	}
                      
                      	xmlnode operator[] (int index)
                      	{
                      		if (m_xmlnodelist!=NULL) return m_xmlnodelist->item[index];
                      		else return NULL;
                      	}
                      
                      private:
                      	MSXML2::IXMLDOMNodeListPtr m_xmlnodelist;
                      };

Open in new window

 

1. Example usage


In order to use the classes you need only to include the above heade.
Sample usage might look like this:
#include "stdafx.h"
                      
                      #include "xml.h"
                      
                      int _tmain(int argc, _TCHAR* argv[])
                      {
                      	xmldocument doc;
                      	doc.load("c:\\inventory.xml");
                      	
                      	// Cast to node
                      	xmlnode root(doc);
                      
                      	// Retrievers
                      	xmlnode magazine = doc["magazine"];
                      	magazine = root["magazine"];
                      
                      	xmlnodelist books = doc("book");
                      	books = root("book");
                      
                      	// Iteraring and getting value
                      	for (int i = 0; i < books.length(); i++)
                      	{
                      		std::string firstname = books[i]["author"]["first-name"].value;
                      		std::wstring lastname = books[i]["author"]["last-name"].value;
                      		int price = books[i]["price"].value;
                      	}
                      
                      	doc.save("c:\\inventory.xml");
                      	return 0;
                      }

Open in new window


2. Class members


The header contains tree classes:
class xmldocument;
class xmlnode;
class xmlnodelist;

xmldocument - represents the document
xmlnode - represents single node
xmlnodelist - represents a list of nodes

xmldocument members:
load - loads a document from file or XML string
save - saves a document to a file
operator[] - extracts single child node
operator() - performs XPATH query and returns list of nodes

xmlnode members:
operator[] - extracts single child node
operator() - performs XPATH query and returns list of nodes
value - this is the value property that has __declspec(property) declared for it, this is Microsoft specific technique that allows to deglare getter and setter for a property. This property returns the inner text of the node in form of xmlvalue struct that has automatic cast operators to any native type.

xmlnodelist members:
length() - returns the length of the list (number of nodes)
operator[] - get the n'th node from the list

3. Conclusion


So there were two interesting points in this implementation:
The usage of __declspec(property)  that allowed me to declare a "property" with get and set accessors and the different operators overloading technique. You are welcome to experiment on the code and extend it further to meet your needs, I hope it gives a good starting point.
1
6,916 Views

Comments (4)

Commented:
std::string firstname = books[i]["author"]["first-name"].value;

Do you think this code is the C++ style?
It's not a complain. It is nice. It is great from the theoretical point of view.
But from the practical point of view, I think, it's better to use C# than overload C++ code with such tricks. Probably, it was not very convinient to debug such code?
It is a good way to "hide" the implementation.
could you show me the .xml document you used for this example? it would really help me understand what is going on inside the data-receival loop

Author

Commented:
Since this was written a while ago... I don't have an access to the data already, however any sample XML could be used, like the sample Microsoft XML used in their examples:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms762271(v=vs.85).aspx
thank you! I got it working now

Have a question about something in this article? You can receive help directly from the article author. Sign up for a free trial to get started.