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
{
string xmlFileName = "books.xml";
XPathDocument xmlPathDoc = new XPathDocument(xmlFileName);
XPathNavigator xNav = xmlPathDoc.CreateNavigator();
NavigateBooksXml(xNav);
FindAllTitles(xNav);
FindBooksByCategory(xNav, "It");
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
public static void NavigateBooksXml(XPathNavigator p_xPathNav)
{
p_xPathNav.MoveToRoot();
p_xPathNav.MoveToFirstChild();
p_xPathNav.MoveToFirstChild();
Console.WriteLine("Printing contents of books.xml:");
do
{
if (p_xPathNav.MoveToFirstAttribute())
{
Console.WriteLine(p_xPathNav.Name + "=" + p_xPathNav.Value);
p_xPathNav.MoveToParent();
}
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
public static void FindAllTitles(XPathNavigator p_xPathNav)
{
XPathNodeIterator xPathIt = p_xPathNav.Select("//book/title");
if (xPathIt.Count > 0)
{
Console.WriteLine("");
Console.WriteLine("The catalog contains the following titles:");
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.
public static void FindBooksByCategory(XPathNavigator p_xPathNav,string p_Category)
{
string query = "//book[@category=\'" + p_Category + "\']";
XPathNodeIterator xPathIt = p_xPathNav.Select(query);
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.