<

XML++

Published on
8,904 Points
5,804 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
Enjoy this complimentary article view.

Get unlimited access to our entire library of technical procedures, guides, and tutorials written by certified industry professionals.

Get 7 days free
Click here to view the full article

Using this article for work? Experts Exchange can benefit your whole team.

Learn More
COLLABORATE WITH CERTIFIED PROFESSIONALS
Experts Exchange is a tech solutions provider where users receive personalized tech help from vetted certified professionals. These industry professionals also write and publish relevant articles on our site.
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.
Learn from the best.