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

Using XPathNavigator in C#

, 13 Jan 2010
Rate this:
Please Sign up or sign in to vote.
How to use XPathNavigator to iterate through XML documents.

Introduction

Thanks for taking a look at my first article. In the past and currently, CodeProject.com has been a life-saver, and is the first place I look when I get stuck on a project. I have stacks of notes, and while I'm unemployed, I'd like to give back to this community. I have a .NET programming background, and love working with C# and ASP.NET. XML is increasingly used everywhere lately. In this article (and hopefully future articles), I hope to provide beginners a decent foundation for navigating XML documents using C#, as well as a quick reference for any programmer using C# and XML.

The code provided and shown below will be using XPathNavigator, XPathIterator, and an XPath query to show you how to search through an XML document.

Before we move on, I'd like to note that this code isn't ground-breaking, but I'm trying to bring this to you in a new light. This example uses a C# Console project, but can easily be converted to a WinForms project to make the results look pretty.

Let's begin

First, we will create a string representing where the location of the XML file that we will be using. Next, we will use XPathDocument and load the string path into the constructor. To use this project, you will need to include System.Xml and System.Xml.XPath.

Note that XPathDocument has a data model that is read-only. It also only covers the significant parts of the XML, leaving out details such as DTDs, entities, CDATA, and no adjacent text nodes. It is the preferred data store for read-only scenarios, especially when XPath or XSLT is involved. If you are looking for something more robust, I would suggest using XmlDocument in place of XPathDocument.

Next, we will create an XPathNavigator object from the XPathDocument by calling the CreateNavigator() method. Before we look at the code, it is usually smart to place this code within a try..catch block to catch any errors.

Setting up the code

using System;
using System.Xml;
using System.Xml.XPath;

namespace UseXPathNavigator
{

   class BooksXmlNavigator
   {

    [STAThread]
    static void Main(string[] args)
    {
        try
        {
            //this is a string representing where the xml file is located
            string xmlFileName = "books.xml";

            // create an XPathDocument object
            XPathDocument xmlPathDoc = new  XPathDocument(xmlFileName);

            // create a navigator for the xpath doc
            XPathNavigator xNav = xmlPathDoc.CreateNavigator();

            //navigate and print the document
            NavigateBooksXml(xNav);

            //navigate and print all the titles
            FindAllTitles(xNav);

            //navigate the xml doc and search for books that are in the category 'It'
            FindBooksByCategory(xNav, "It");

            //To keep the screen up and waiting for the user to hit return
            Console.Read();
        }
        catch (XmlException e)
        {
            Console.WriteLine("Exception: " + e.ToString());
        }
    }

Navigate and print the document

Here, I will attempt to show you how to navigate through an XML document and display it on the screen. I do not use any formatting to display the contents of the document, so it doesn't look very pretty. Here, I am strictly trying to demonstrate how to navigate a simple XML document using an XPathNavigator object. If you are interested in displaying the information in a visually appealing way, I'd suggest using an XmlDocument object (instead of our XPathDocument). I'll reserve using XmlDocument for a future article.

The idea here is to use the XPathNavigator object and move to the first element or root. Then, go to the first child element of the root, then begin a loop to read through the document. Within the loop, I first check to see if there is an attribute(s) associated with the element, by calling MoveToFirstAttribute() in an if statement. If there is an attribute, I read its name and value, then return the navigator to the element it was just at, by calling the MoveToParent() method. Then, I begin displaying the child nodes, and loop to see if there are any nested nodes.

NavigateBooksXml method

/*
   NavigateBooksXml method
   Accpets: XPathNavigator p_xPathNav
   Returns: Nothing
   Purpose: This method will iterate through the xml document provided in the 
   XPathNavigator object and display it to the console    
*/

public static void NavigateBooksXml(XPathNavigator p_xPathNav)
{
    // move to the root and the first element - <books>
    p_xPathNav.MoveToRoot();
    p_xPathNav.MoveToFirstChild();

    // move to first <book> element
    p_xPathNav.MoveToFirstChild();
    Console.WriteLine("Printing contents of books.xml:");

    //begin looping through the nodes
    do
    {
        // list attribute;
        if (p_xPathNav.MoveToFirstAttribute())
        {
            Console.WriteLine(p_xPathNav.Name + "=" + p_xPathNav.Value);
            // go back from the attributes to the parent element
            p_xPathNav.MoveToParent();
        }

        //display the child nodes
        if (p_xPathNav.MoveToFirstChild())
        {
            Console.WriteLine(p_xPathNav.Name + "=" + p_xPathNav.Value);
            while (p_xPathNav.MoveToNext())
            {
                Console.WriteLine(p_xPathNav.Name + "=" + p_xPathNav.Value);
            }
            p_xPathNav.MoveToParent();
        }
    } while (p_xPathNav.MoveToNext());
}

Using an XPath query

Next, I'll show you how to use a simple XPath query. You can perform a query on the XPathNavigator object by calling its Select() method. I'll try to dissect the query for you. The //book means to select all elements within the document regardless of where they are found in the document. The query is then followed by /titles, because we are looking within all the book elements for the title.

You can perform many different types of searches. For example, //@lang will select all attributes that are named lang because the @ sign selects attributes of an element. You can also use the double-slashes later in the expression, such as books//book will select all book elements that are children of the books root. A single period . within a query will select the current node, and two periods .. within the query will select the parent of the current node.

FindAllTitles method

/*
   FindAllTitles method
   Accpets: XPathNavigator p_xPathNav
   Returns: Nothing
   Purpose: This method will iterate through the xml document provided in the 
   XPathNavigator object and display all of the title elements    
*/

public static void FindAllTitles(XPathNavigator p_xPathNav)
{
    //run the XPath query
    XPathNodeIterator xPathIt = p_xPathNav.Select("//book/title");

    //use the XPathNodeIterator to display the results
    if (xPathIt.Count > 0) 
    {
        Console.WriteLine("");
        Console.WriteLine("The catalog contains the following titles:");

        //begin to loop through the titles and begin to display them
        while (xPathIt.MoveNext())
        {
            Console.WriteLine(xPathIt.Current.Value);
        }
    } else 
    {
        Console.WriteLine("No titles found in catalog.");
    }
}

Find books by category

This last method demonstrates searching through an XML document to find specific element(s). You could accept a value that the user is searching for, then send that value to this method and search the XML document for what the user wants.

This method accepts an XPathNavigator object to iterate through the XML document and (in this case) a category string representing what you want to search for. It uses the XPath query //book[@ category="" + Category + ""]", which says to select all book elements that have an attribute of the passed in category.

/*
   FindBooksByCategory method
   Accpets: XPathNavigator object
            string p_Category
   Returns: Nothing
   Purpose: This method will iterate through the XML document provided 
            in the XPathNavigator object and search book elements 
            for the category attribute passed into the method
*/

public static void FindBooksByCategory(XPathNavigator p_xPathNav,string p_Category)
{
    string query = "//book[@category=\'" + p_Category + "\']";
    XPathNodeIterator xPathIt = p_xPathNav.Select(query);

    //use the XPathNodeIterator to display the results
    if (xPathIt.Count > 0)
    {
        Console.WriteLine("");
        Console.WriteLine("The following books are " + 
                          "in the \{0\} category:", p_Category);
        while (xPathIt.MoveNext())
        {
            Console.WriteLine(xPathIt.Current.Value);
        }
    }
    else
    {
        Console.WriteLine("No books found in the \{0\} category", p_Category);
    }
}

History

This is my first contribution to CodeProject, and I hope to follow this article up with a few more XML parsing articles using C# and SQL.

I'll make sure to post links to related articles in the future that are related to this one.

License

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

About the Author

Danny Hauptman

United States United States
No Biography provided

Comments and Discussions

 
GeneralMy vote of 5 PinmemberDon Jomar Hombrebueno26-Jun-11 21:26 
GeneralReading the attributes PinmemberHarish Tallapragada21-Sep-10 2:33 
Generalvtd-xml PinmemberJimmy Zhang26-Feb-10 22:32 
QuestionNice, but I guess most folk would use XLINQ these days right? PinmvpSacha Barber13-Jan-10 10:13 
AnswerRe: Nice, but I guess most folk would use XLINQ these days right? PinmemberDanny Hauptman13-Jan-10 10:25 
GeneralRe: Nice, but I guess most folk would use XLINQ these days right? PinmvpSacha Barber13-Jan-10 10:38 
AnswerRe: Nice, but I guess most folk would use XLINQ these days right? PinmemberPaul Selormey13-Jan-10 14:39 
AnswerRe: Nice, but I guess most folk would use XLINQ these days right? PinmvpSacha Barber13-Jan-10 21:43 
GeneralRe: Nice, but I guess most folk would use XLINQ these days right? PinmemberRogerDW14-Jan-10 2:16 
AnswerRe: Nice, but I guess most folk would use XLINQ these days right? PinmemberDanny Hauptman14-Jan-10 3:14 
GeneralRe: Nice, but I guess most folk would use XLINQ these days right? PinmvpSacha Barber14-Jan-10 4:19 

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

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web01 | 2.8.140721.1 | Last Updated 13 Jan 2010
Article Copyright 2010 by Danny Hauptman
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid