Reading XML files is a necessary technique to retrieve information from an XML file. Say, for example, you store your configuration settings in an XML file, you can retrieve the settings from the XML file when the application is loading. We will create an example application to demonstrate how we can read data from an XML file. The example application we will create retrieves individual records from an XML file. We will provide buttons to navigate and read other existing records. Create a new Windows Forms Application and create a form similar to the one in Figure 1.

Figure 1

Use the names buttonFirstbuttonPreviousbuttonNext, and buttonLast for the four button controls. Use the names textBoxNametextBoxAge, and textBoxGender for the three text boxes.

In this tutorial, we will be needing a sample XML file that contains the records that will be read by our application. Create a new XML file by clicking the Add New Item button in the toolbar.

Then choose XML file from the list of templates. Name the file sample.xml. Visual Studio will create an XML file for you. Delete its contents and use the following XML markup.

<?xml version="1.0" encoding="utf-8" ?>
<Persons>
  <Person name="John Smith">
    <Age>30</Age>
    <Gender>Male</Gender>
  </Person>
  <Person name="Mike Folley">
    <Age>25</Age>
    <Gender>Male</Gender>
  </Person>
  <Person name="Lisa Carter">
    <Age>22</Age>
    <Gender>Female</Gender>
  </Person>
  <Person name="Jerry Frost">
    <Age>27</Age>
    <Gender>Male</Gender>
  </Person>
  <Person name="Adam Wong">
    <Age>35</Age>
    <Gender>Male</Gender>
  </Person>
</Persons>

Figure 1

The XML file contains five records of persons. Our application will start reading the first record and the user is allowed to see the other records by pressing the navigation buttons.

Switch to code view and import the required System.Xml namespace.

using System.Xml;

Then add the following members to the Form1 class.

private XmlDocument doc;
private XmlElement root;
private XmlElement currentPerson;
private const string PATH = @"....sample.xml";
private int current = 0;
private int max;

The doc of type XmlDocument is used to load an XML file and manipulate its content. The root variable will be used to hold the root element of the document. The currentPerson variable is used to hold the currently selected person element. We used the path “….sample.xml” because the XML file we created earlier is located two directories up the executable file (.. means go up one directory). Again, you change this to a different location where the XML file is located. The current variable is used to track which record to show using a 0-based index. It is initialized to 0 to indicate that the current record is the first record. The max variable will be used to store the maximum index which will be useful later.

We need to create a utility method that will be used by the event handlers to show the details of the selected record to the text box. Add this method inside the Form1 class.

private void ShowDetails(XmlElement currentPerson)
{
    textBoxName.Text = currentPerson.Attributes["name"].Value;
    textBoxAge.Text = currentPerson.GetElementsByTagName("Age")[0].InnerText;
    textBoxGender.Text = currentPerson.GetElementsByTagName("Gender")[0].InnerText;
}

This method accepts the currently selected person. First, the value of the attribute “name” is retrieved and displayed in textBoxName. We used the Attribute property of the XmlElement class and used a string indexer which represents the name of the attribute. We then use the Value property of that specified attribute.

We retrieve the value of the Age element by using the XmlElement’s GetElementByTagName method. We pass the name of the element and the method searches all the child elements which has the specified name and returns them as a XmlNodeList. Since XmlNodeList is a collection, and there is only one expected result, we can access the first matching element by using the index 0.

textBoxAge.Text = currentPerson.GetElementsByTagName("Age")[0].InnerText;

This line might be quite confusing to beginners because I did everything in one line. The line simply means get the first element [0] of the collection returned by GetElementByTagName and then access the InnerText property of that first element. We can rewrite this one line of code into a much readable code but it will require more code as seen below.

XmlNodeList results = currentPerson.GetElementsByTagName("Age");
XmlNode first = results[0];
textBoxAge.Text = first.InnerText;

The next line of code is similar to the one for retrieving the Age but this time, the Gender element is searched by the GetElementsByTagName method.

With the required utility method completed, we can now create our event handlers. Switch to Design View by clicking the Design tab or by using the shortcut Shift+F7.

Click a blank space on the form to create an event handler for its Load event. Use the following code for the event handler.

private void Form1_Load(object sender, EventArgs e)
{
    doc = new XmlDocument();
    doc.Load(PATH);

    //Get root element
    root = doc.DocumentElement;

    //Determine maximum possible index
    max = root.GetElementsByTagName("Person").Count - 1;

    //Get the record at the current index
    currentPerson = (XmlElement)root.ChildNodes[current];

    //Show the record information
    ShowDetails(currentPerson);
}

This code will execute when the form is finished loading. It will retrieve and display the first record in the XML file. We first create an XmlDocument object. Then we load the XML file specified by the PATH using the Load method of the XmlDocument class. We retrieve the root element by using the DocumentElement property. We calculated the max possible index by getting all the child elements with the name of Person and then count them. We subtract it by 1 because indexes are 0-based. We will be needing the value of max later. We then retrieve the first person by using the ChildNodes method and passing the value of current (which is now 0) as the index. The ChildNodes property is a collection of all the child nodes of a node, and by passing 0 as the index, we can retrieve the first record. Since the ChildNodes consists of XmlNode objects, we need to convert the node to an XmlElement so we can store it in an XmlElementobject. Of course, we can also use the GetElementsByTagName method but I used ChildNodes method to demonstrate to you an alternative technique. We now pass the retrieved element to the method we created earlier. Passing it to that method extracts the details from the currently selected person element.

Return to the Designer and double click buttonFirst. Use the following event handler code.

private void buttonFirst_Click(object sender, EventArgs e)
{
    current = 0;
    currentPerson = (XmlElement)root.ChildNodes[current];
    ShowDetails(currentPerson);
}

The first line resets the current index to 0 and then retrieves the child node at index 0. We then used the ShowDetails method to show the details of the retrieved XmlElement. Let’s now add the event handler for the buttonPrevious.

private void buttonPrevious_Click(object sender, EventArgs e)
{
    current = (current - 1 < 0) ? 0 : current - 1;
    currentPerson = (XmlElement)root.ChildNodes[current];
    ShowDetails(currentPerson);
}

The code is similar the buttonFirst‘s event handler except for the first line. The previous record is simply represented by the expression (current – 1). The first line uses the conditional statement testing whether the previous element is less than zero. If it is, we simply assign zero and prevent the user from accessing negative indexes. This is to prevent IndexOutOfRangeException. If the user is at the beginning record, then clicking buttonPrevious will have no effect. If the previous index is equal or greater than zero, then the current index is assigned with its value decreased by 1 to indicate that we are now showing the previous record. The record with the new index is then retrieved and shown using the ShowDetails method.

Let’s now add the event handler for buttonNext which shows the next record.

private void buttonNext_Click(object sender, EventArgs e)
{
    current = (current + 1 > max) ? max : current + 1;
    currentPerson = (XmlElement)root.ChildNodes[current];
    ShowDetails(currentPerson);
}

Again, the only difference here is calculating the new current index. The next record is represented by the expression (current + 1) and we test if it will exceed the maximum possible index which is stored in variable max. If it does exceed, then we simply assign the value of max as the current index. If the next index is equal to or less than the max, then the next index is assigned as the new current index. The element at the new index is retrieved and shown to the user.

Finally, add an event handler to buttonLast by double clicking it in the Designer. Use the following code.

private void buttonLast_Click(object sender, EventArgs e)
{
    current = max;
    currentPerson = (XmlElement)root.ChildNodes[current];
    ShowDetails(currentPerson);
}

Since we will be retrieving the last record, the current index is simply assigned with the final index indicated by the value of max. The element is then retrieved and shown to the user.

Execute the application and you will be presented with the data of the first record. Click the buttons to move to other records in the XML file. You have now successfully created an application that reads records from an XML file using the classes of the XML DOM.