<

XML++

Published on
9,207 Points
6,107 Views
1 Endorsement
Last Modified:
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
Author:SunnyDark
Ask questions about what you read
If you have a question about something within an article, you can receive help directly from the article author. Experts Exchange article authors are available to answer questions and further the discussion.
Get 7 days free