Developer

Traverse XML with .NET's XPathNavigator

The .NET XPathNavigator class can help you navigate XML documents. Here's how.

This article originally appeared as an XML e-newsletter.

By Brian Schaffner

Working with XML data means both reading and writing XML documents. In addition to simply pulling the document into an application or creating a new document, you're often faced with the task of navigating through a document to find a specific reference. Let's look at the .NET XPathNavigator class and see how you can use it to help navigate XML documents.

Sample document

We'll refer throughout this article to a sample XML document that contains the text of William Shakespeare's Hamlet. This document is freely available in the public domain and you can download it from the ibiblio Web site.

Navigating Hamlet

One of the first things we'll do with Hamlet is use the XPathNavigator to locate one of the most famous of Shakespeare's lines: "To be, or not to be." We'll use Visual Basic to provide the functionality and implement the XPathNavigator class.

To begin, we'll create a new form that contains a few visual components. We'll start with a TextBox, two Buttons, and a DataGrid. We'll also add an OpenFileDialog component so that it's easier to load the various Shakespeare XML documents into the sample application.

The TextBox will be used to capture the search criteria. The first button should be labeled Load and the other button labeled Search. The Load button will be used to load the XML document into the application, while the Search button is used to evaluate an XPath query against the document.

Finally, the DataGrid is used to display the results of our search. Basically, we're going to implement an application that will search one of the Shakespeare plays for a particular phrase and display the results in the DataGrid, indicating who utters the line along with the full speech.

Adding the glue

If you double-click the Load button, VB will open the code editor for that button's click method—which you should edit to look like Listing A:

Listing A: Load button click method
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
  Dim filename As String
  OpenFileDialog1.ShowDialog()
  filename = OpenFileDialog1.FileName
  xmldoc = Nothing
  xmldoc = New System.Xml.XmlDocument()
  xmldoc.Load(filename)
  loaded = True
End Sub

You should immediately notice that we've assigned a value to both xmldoc variables and loaded without allocating or dimensioning them first. The reason is that you need to declare these as global variables for your form. That declaration looks like this:

  Dim xmldoc As System.Xml.XmlDocument
  Dim loaded As Boolean = False

Next, double-click the Search button to open the code editor for its click method. This button will activate the XPath query and display the results in the DataGrid. Listing B shows the code for this method:

Listing B: Search button click method
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
  Dim xmlnav As System.Xml.XPath.XPathNavigator
  Dim xmlitr As System.Xml.XPath.XPathNodeIterator
  Dim speaker As String
  Dim line As String
  Dim dt As New DataTable()
  Dim dr As DataRow
  Dim i As Integer

  DataGrid1.DataSource = New DataView(dt)

  If loaded Then
    xmlnav = xmldoc.CreateNavigator()
    xmlitr = xmlnav.Select("//LINE[contains(., """ & TextBox1.Text & """)]/..")
    dt.Columns.Add("Speaker", GetType(String))
    dt.Columns.Add("Line", GetType(String))
    While (xmlitr.MoveNext())
      Dim nav2 As Xml.XPath.XPathNavigator = xmlitr.Current.Clone
      nav2.MoveToFirstChild()
      speaker = nav2.Value
      i = 0
      While nav2.MoveToNext()
        line = nav2.Value
        dr = dt.NewRow
        If (i = 0) Then
          dr(0) = speaker
        Else
          dr(0) = ""
        End If
        dr(1) = line
        dt.Rows.Add(dr)
        i = i + 1
      End While
      DataGrid1.DataSource = New DataView(dt)
    End While
  End If
End Sub

The gist of this method is that it uses the XPathNavigator class to query the loaded XML document, and then uses an XPathNodeIterator to walk through the results. The XPathNavigator class is created by the XML document class, and the XPathNodeIterator class is created by XPathNavigator class.

When you make the call to the XPathNavigator's Select() method, it returns an iterator you can use to step through the results. Each time we call the iterator's MoveNext() method, we advance to the next node that was found by the XPath expression.

Running the example

Compile and run the application. First, click the Load button and select the hamlet.xml file you downloaded earlier. Next, type a phrase into the text box—for example: To be, or not to be—and then click Search. You should see the results populated in the DataGrid informing you of who said that line and the full section of the speech.

Brian Schaffner is an associate director for Fujitsu Consulting. He provides architecture, design, and development support for Fujitsu's Technology Consulting practice.

Editor's Picks