Introduction
Following is a quick and dirty C++ XML XPath expression parser.
Background
I started the day checking the web looking for a quick and easy XPath parser for C++. Now, before I begin, I just want to say that I found plenty of XML libraries out there but nothing that quite suited my needs. What got me started on this XPath adventure, you ask? Well, it all started because I am currently writing a dev tool which requires some external settings. Usually, I would place these app settings in the Registry, but on this occasion (as I had a little time), I thought I would have a go at using XML to store my application settings. All was going swimmingly, and I had got to the part where I had written my settings.xml file, and now I wanted to read it back in and navigate my settings file. After doing some internet prodding, it seems that XPath is the easiest and simplest way to do this.
I had a quick play with the .NET classes using C++/CLI and found them a breeze to use, but I wanted to keep my application to be fully C++ native on this occasion, which is why I decided to write this quick and dirty XPathParser
class.
How to Use the XPathParser Class
Using the XPathParser
class is very straightforward.
First, add the source files (XPathParser.cpp and XPathParser.h) into the directory you wish to use them from, and then add the files to your Visual Studio project. Include XPathParser.h in the file you want to use the class:
#include "XPathParser.h"
The next thing to do is to include the namespace XPathNS
.
using namespace XPathNS;
At this point, we are ready to rock and roll. All we need to do is instantiate an instance of the XPathParser
, passing through the name of the XML file we are going to throw XPath expressions at.
XPthParser xPath( "books.xml" )
If you have made it this far, you'd be foolish to stop coding now. Now, we get to try out some XPath expressions (just like below):
std::vector<XMLNode> nodeList1 = xPath.selectNodes( "//catalog//book//author" );
std::vector<XMLNode> nodeList2 = xPath.selectNodes( "//author" );
std::vector<XMLNode> nodeList3 = xPath.selectNodes( "//price" );
std::vector<XMLNode> nodeList4 = xPath.selectNodes( "//book" );
std::vector<XMLNode> nodeList5 = xPath.selectNodes( "//@id" );
std::vector<XMLNode> nodeList6 = xPath.selectNodes( "//book[last()]" );
std::vector<XMLNode> nodeList7 = xPath.selectNodes( "//book[@id='bk103']" );
std::vector<XMLNode> nodeList8 =
xPath.selectNodes( "/catalog/book[price>35.00]/title" );
XMLNode node1 = xPath.selectSingleNode( "//author" );
Simple as hey! Are we forgetting something? Ahh yes.. Each XPath expression yields a list of XMLNode
s. An XMLNode
is made up of the "XML name", the actual "XML value", and "any XML attributes" associated with the XMLNode
. For reference, here is what the XMLNode
class looks like:
struct XMLAttribute
{
std::string value_;
std::string name_;
};
struct XMLNode
{
std::string xml_;
std::string value_;
std::string name_;
std::vector<XMLAttribute> nodeAttributes_;
};
Getting back to some sample code, here is a complete example of using the XPathParser
class:
using namespace XPathNS;
XPathParser xPath( "books.xml" )
std::vector<XMLNode> nodeList =
xPath.selectNodes( "/catalog/book[price>35.00]/title" );
for ( int loopCnt = 0; loopCnt < nodeList.size(); loopCnt++ )
{
XMLNode node = nodeList[loopCnt];
std::cout << "name : " << node.name_ << std::endl;
std::cout << "value: " << node.value_ << std::endl;
std::cout << "num attributes : " << node.nodeAttributes.size() << std::endl;
for ( int attribCnt = 0; attribCnt < node.nodeAttributes.size(); attribCnt++ )
{
XMLAttribute attrib = node.nodeAttributes[attribCnt];
std::cout << "attribute name : " << attrib.name_ << std::endl;
std::cout << "attribute value: " << attrib.value_ << std::endl;
}
}
Points of Interest
Just to note, in real life, the XPathParser
class is nothing more than a wrapper for MSXML 6.0, which is why this article is aptly titled quick & dirty. More information can be found about MSXML at the following website: http://www.microsoft.com/downloads/details.aspx?familyid=993c0bcf-4009-be21-27e85e1857b1&displaylang=en.
The sample XML file that I used was from the MSDN website: http://msdn2.microsoft.com/en-us/library/ms762271.aspx.
The sample application written using Visual Studio 2005 SP2.
History
No history here!!