Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C++

Quick & Dirty XML XPath Parser

3.06/5 (8 votes)
7 May 2007CPOL2 min read 1   857  
A simple XPath parser.

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:

C++
#include "XPathParser.h"

The next thing to do is to include the namespace XPathNS.

C++
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.

C++
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):

C++
// drill down and select all author elements
std::vector<XMLNode> nodeList1 = xPath.selectNodes( "//catalog//book//author" );

// select all author elements
std::vector<XMLNode> nodeList2 = xPath.selectNodes( "//author" );     

// select all price elements
std::vector<XMLNode> nodeList3 = xPath.selectNodes( "//price" ); 

// select all books elements
std::vector<XMLNode> nodeList4 = xPath.selectNodes( "//book" );   

// select all attributes named id
std::vector<XMLNode> nodeList5 = xPath.selectNodes( "//@id" ); 

// select the last book element
std::vector<XMLNode> nodeList6 = xPath.selectNodes( "//book[last()]" );   

// select all book elements with id equal to bk103
std::vector<XMLNode> nodeList7 = xPath.selectNodes( "//book[@id='bk103']" );   

// select all book titles with price > 35 quid
std::vector<XMLNode> nodeList8 = 
            xPath.selectNodes( "/catalog/book[price>35.00]/title" ); 

// select the first node matching author
XMLNode node1 = xPath.selectSingleNode( "//author" );

Simple as hey! Are we forgetting something? Ahh yes.. Each XPath expression yields a list of XMLNodes. 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:

C++
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:

C++
using namespace XPathNS;

XPathParser xPath( "books.xml" )
std::vector<XMLNode> nodeList = 
     xPath.selectNodes( "/catalog/book[price>35.00]/title" ); 

// now lets output our nodeList

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!!

License

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