Click here to Skip to main content
Click here to Skip to main content

Quick & Dirty XML XPath Parser

By , 7 May 2007
 

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

// 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:

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" ); 

// 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)

About the Author

flippydeflippydebop
United Kingdom United Kingdom
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralMy vote of 1 PinmemberMember 42359838 Mar '10 - 8:03 
Really poor wrapper around msxml
QuestionXML File doesn't exist !!! PinmemberCSharpJSharp21 Nov '08 - 0:07 
When used the constructor to load the XML file :
 
XPthParser xPath( "books.xml" )
 
and the XML file doesn't exist, I have an exception when I select node.
 
Is there a way to verify that XML file is loaded or failed to load ?
 
Thanx
AnswerRe: XML File doesn't exist !!! Pinmemberjxtamarc6 Mar '09 - 1:14 
it does exist.
 
you can find it in the XpathTestBed folder.
 
otherwise you can get it from :
 

http://msdn.microsoft.com/en-us/library/ms762271.aspx[^]
GeneralA.K.A MSXML6 Wrapper PinmemberGeorge L. Jackson8 May '07 - 15:41 
Your XPath Parser is not lightweight but I believe it is dirty since you are just wrapping the XPath functionality found in MSXML6. MSXML6 is certainly not lightweight. IMHO, your code and article is a sham.
 
"We make a living by what we get, we make a life by what we give." --Winston Churchill

GeneralRe: A.K.A MSXML6 Wrapper Pinmemberflippydeflippydebop8 May '07 - 20:57 
Permalink | Advertise | Privacy | Mobile
Web04 | 2.6.130516.1 | Last Updated 7 May 2007
Article Copyright 2007 by flippydeflippydebop
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid