Creating an Element

Introduction

To create an XML element, you can directly type the XML code in a document. When the file is saved, it is ready to be processed. Here is an example of a file named videos.xml:

<?xml version="1.0" encoding="utf-8" ?>
<videos>
    <title>The Distinguished Gentleman</title>
</videos>

In some applications, you will want the user to provide you with the necessary value(s) to create an element. Fortunately, the XmlDocument, the XmlNode, and the XmlElement classes provide all the properties and methods necessary to perform the routine operations of an XML file, an element, or a node. The operations include locating a node, adding a new element, or deleting a node.

Before performing an operation, you will usually need to decide in what section of the file you want the action to be applied. As it happens, you have the root node, a particular node inside the document, parent of a node, the sibling of a node, etc. To get to a node, you will usually first get a reference to its XmlElement. To do this, you can declare an XmlElement variable and initialize it with that reference.

Appending an Element

To assist with programmatically creating a new element, the XmlDocument class provides a method named CreateElement. It is overloaded with three versions. One of the versions uses the following syntax:

public XmlElement CreateElement(string name);

To create a new element, call this method and pass it the name of the element. For example, imagine you want to add a new Title element to the above XML document. You would start with code as follows:

using System.Xml;

namespace VideosCollection
{
    public partial class Exercise : Form
    {
        public Exercise()
        {
            InitializeComponent();
        }

        private void btnDocument_Click(object sender, EventArgs e)
        {
            string strVideos = "videos.xml";
            XmlDocument xdVideos = new XmlDocument();

            if (File.Exists(strVideos))
            {
                xdVideos.Load(strVideos);

                XmlElement xeVideo = xdVideos.CreateElement("Title");
            }
        }
    }
}

In order to add the new element to the document, you must specify its position in the tree: whether it would be the first or the last node, whether you want to position it before or after a node of your choice. For example, if you want to add a new Title element to the above file, it would be considered a child of the root; that is, a child of the XmlDocument.DocumentElement property.

To support the positions of existing nodes, the XmlNode class, which is the ancestor of all XML nodes of the .NET Framework, provides various methods. One of these methods is named AppendChild. It is used to add an element as the last child of its parent. The syntax of the XmlNode.AppendChild() method is:

public virtual XmlNode AppendChild(XmlNode newChild);

When calling this method, pass the XmlNode object you had previously created. After adding the node, if you want the file to keep it, you should save it. Here is an example:

private void btnDocument_Click(object sender, EventArgs e)
{
    XmlDocument xdVideos = new();
    string strVideos = "videos.xml";

    if (File.Exists(strVideos))
    {
        xdVideos.Load(strVideos);

        XmlElement xeRoot = xdVideos.DocumentElement!;
        XmlElement xeVideo = xdVideos.CreateElement("title");
        xeRoot.AppendChild(xeVideo);
    }
    else // if (!File.Exists(strVideos))
    {
        // Create the default XML structure
        xdVideos.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                         "<videos></videos>");
    }
            
    xdVideos.Save(strVideos);
}

This would produce:

<?xml version="1.0" encoding="utf-8"?>
<videos>
    <title>The Distinguished Gentleman</title>
    <title />
</videos>

Notice that the newly added element is empty.

Adding the Inner Text of an Element

Suppose you have the following videos.xml file:

<?xml version="1.0" encoding="utf-8"?>
<videos>
    <video>
        <title>The Distinguished Gentleman</title>
        <director>Jonathan Lynn</director>
        <length>112 Minutes</length>
        <format>DVD</format>
        <rating>R</rating>
    </video>
    <video>
        <title>Her Alibi</title>
        <director>Bruce Beresford</director>
        <length>94 Minutes</length>
        <format>DVD</format>
        <rating>PG-13</rating>
    </video>
</videos>

Imagine that you want to add a video element. You have a choice of adding one, more than one, or all child elements of the video node. To perform this operation, one solution you can use is to "build" all child elements of the video element, then add the node as a whole.

We already know that the XmlNode.InnerXml property has a node, its markup, its children and their markup. This means that you can create the child node(s) with its (their) markup(s) as a string and assign that string to an XmlNode.InnerXml string. To do this, you would need the set version of the InnerXml property. It is declared as follows:

public virtual string InnerXml { get; set; }

Here is an example that adds a complete new video node to the above XML file:

using System.Xml;

namespace VideoCollection
{
    public partial class Exercise : Form
    {
        public Exercise()
        {
            InitializeComponent();
        }

        private void btnDocument_Click(object sender, EventArgs e)
        {
            XmlDocument xdVideos = new();
            string strVideos = @"E:\Videos Collection\Videos.xml";
            FileInfo fiVideos = new FileInfo(strVideos);

            if (fiVideos.Exists == true)
            {
                xdVideos.Load(fiVideos.FullName);

                XmlElement xeVideo = xdVideos.CreateElement("video");
                string strVideo    = "<title>Other People&#039;s Money</title>" +
                                     "<director>Alan Brunstein</director>" +
                                     "<length>114 Minutes</length>" +
                                     "<format>VHS</format>" +
                                     "<rating>PG-13</rating>";

                xeVideo.InnerXml = strVideo;
                xdVideos.DocumentElement?.AppendChild(xeVideo);
            }
            else // if (!File.Exists(strVideos))
            {
                // Create the default XML structure
                xdVideos.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                                 "<videos></videos>");
            }

            xdVideos.Save(fiVideos.FullName);
        }
    }
}

This would produce:

<?xml version="1.0" encoding="utf-8"?>
<videos>
    <video>
        <title>The Distinguished Gentleman</title>
        <director>Jonathan Lynn</director>
        <length>112 Minutes</length>
        <format>DVD</format>
        <rating>R</rating>
    </video>
    <video>
        <title>Her Alibi</title>
        <director>Bruce Beresford</director>
        <length>94 Minutes</length>
        <format>DVD</format>
        <rating>PG-13</rating>
    </video>
    <video>
        <title>Other People's Money</title>
        <director>Alan Brunstein</director>
        <length>114 Minutes</length>
        <format>VHS</format>
        <rating>PG-13</rating>
    </video>
</videos>

As we sometimes mention it, a variable is necessary only if you are plannieng to use the same value many times. Otherwise, you can omit a variable and type the value directly where you need it. As a result, the above code can be written as follows:

using System.Xml;

namespace VideoCollection
{
    public partial class Exercise : Form
    {
        public Exercise()
        {
            InitializeComponent();
        }

        private void btnDocument_Click(object sender, EventArgs e)
        {
            XmlDocument xdVideos = new();
            string strVideos = @"E:\Videos Collection\Videos2.xml";
            FileInfo fiVideos = new FileInfo(strVideos);

            if (fiVideos.Exists == true)
            {
                xdVideos.Load(fiVideos.FullName);

                XmlElement xeVideo = xdVideos.CreateElement("video");
                xeVideo.InnerXml   = "<title>Other People&#039;s Money</title>" +
                                     "<director>Alan Brunstein</director>" +
                                     "<length>114 Minutes</length>" +
                                     "<format>VHS</format>" +
                                     "<rating>PG-13</rating>";
                xdVideos.DocumentElement?.AppendChild(xeVideo);
            }
            else
            {
                // Create the default XML structure
                xdVideos.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                                 "<videos></videos>");
            }

            xdVideos.Save(fiVideos.FullName);
        }
    }
}

Adding an Element With Value

Consider the following document of an XML file named videos.xml:

<?xml version="1.0" encoding="utf-8" ?>
<videos>
    <title>The Distinguished Gentleman</title>
</videos>

If you want the element to have a value, the XmlDocument class provides a method named CreateTextNode(). The syntax of this method is:

public virtual XmlText CreateTextNode(string text);

This method returns an XmlText value. This method takes as argument the string that would constitute the value of the element. Before calling it, you should have used the XmlNode.AppendChild() method to create a node. Calling this method on the LastChild node of the one that called the AppendChild() method would specify the value of the new node. Here is an example:

private void btnDocument_Click(object sender, EventArgs e)
{
    string strVideos = "videos.xml";
    var xdVideos     = new XmlDocument();

    if (File.Exists(strVideos))
    {
        xdVideos.Load(strVideos);

        XmlElement xeRoot = xdVideos.DocumentElement!;

        XmlElement xeVideo = xdVideos.CreateElement("title");
        XmlText txtvideo = xdVideos.CreateTextNode("Basic Instinct");
        xeRoot.AppendChild(xeVideo);
        xeRoot.LastChild?.AppendChild(txtvideo);
    }
    else // if (!File.Exists(strVideos))
    {
        // Create the default XML structure
        xdVideos.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                          "<videos></videos>");
    }
            
    xdVideos.Save(strVideos);
}

This would produce:

<?xml version="1.0" encoding="utf-8"?>
<videos>
    <title>The Distinguished Gentleman</title>
    <title>Basic Instinct</title>
</videos>

The combination of calls to XmlDocument.CreateElement() and XmlDocument.CreateTextNode() allows you to create a new element that has a value.

Consider the following document of an XML file named "videos.xml":

<?xml version="1.0" encoding="utf-8"?>
<videos>
    <video>
        <title>The Distinguished Gentleman</title>
    </video>
    <video>
        <title>Basic Instinct</title>
    </video>
</videos>

Notice that the root, videos, has a repetitive child named video. This video child has its own child named Title. Imagine that you want to add a new video node that has a child. To do this, first create an empty video node as a child of the root. We learned earlier how to do that:

private void btnDocument_Click(object sender, EventArgs e)
{
    string strVideos = "videos.xml";
    XmlDocument xdVideos = new();

    if (File.Exists(strVideos))
    {
        xdVideos.Load(strVideos);

        XmlElement xeRoot = xdVideos.DocumentElement!;
        XmlElement xeVideo = xdVideos.CreateElement("video");
        xeRoot.AppendChild(xeVideo);
    }
    else // if (!File.Exists(strVideos))
    {
        // Create the default XML structure
        xdVideos.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                          "<videos></videos>");
    }
            
    xdVideos.Save(strVideos);
}

After creating the new child of the root, initialize the grand child with the desired name (the name doesn't have to be one of the existing names) and a value (which is optional if you don't want the new node to have a value). Once the new node is ready, append it as the last child of the root. If this new node has a value, append its XmlText object as the LastChild of the LastChild of the root. Here is an example of how you would do this:

private void btnDocument_Click(object sender, EventArgs e)
{
    string strVideos = "videos.xml";
    XmlDocument xdVideos = new XmlDocument();

    if (File.Exists(strVideos))
    {
        xdVideos.Load(strVideos);

        XmlElement xeRoot = xdVideos.DocumentElement!;
        XmlElement xeVideo = xdVideos.CreateElement("video");
        xeRoot.AppendChild(xeVideo);

        xeVideo = xdVideos.CreateElement("title");
        XmlText txtvideo = xdVideos.CreateTextNode("Her Alibi");

        xeRoot.LastChild?.AppendChild(xeVideo);
        xeRoot.LastChild?.LastChild?.AppendChild(txtvideo);
    }
    else // if (!File.Exists(strVideos))
    {
        // Create the default XML structure
        xdVideos.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                          "<videos></videos>");
    }
            
    xdVideos.Save(strVideos);
}

This would produce:

<?xml version="1.0" encoding="utf-8"?>
<videos>
    <video>
        <title>The Distinguished Gentleman</title>
    </video>
    <video>
        <title>Basic Instinct</title>
    </video>
    <video>
        <title>Her Alibi</title>
    </video>
</videos>

Now consider the following file:

<?xml version="1.0" encoding="utf-8"?>
<videos>
    <video>
        <title>The Distinguished Gentleman</title>
        <director>Jonathan Lynn</director>
        <length>112 Minutes</length>
        <format>DVD</format>
        <rating>R</rating>
    </video>
    <video>
        <title>Her Alibi</title>
        <director>Bruce Beresford</director>
        <length>94 Minutes</length>
        <format>DVD</format>
        <rating>PG-13</rating>
    </video>
</videos>

The root, videos, has a child named video. The video node has many child nodes. By now, we know how to add a child to the root. We also saw how to add a grand child with value to the root. To had many (grand) children to a node, first build the node, add it to the root, then continuously add the necessary nodes, one at a time, including its name and its optional value. This would be done as follows:

private void btnDocument_Click(object sender, EventArgs e)
{
    string strVideos = "videos.xml";
    var xdVideos = new XmlDocument();

    if (File.Exists(strVideos))
    {
        xdVideos.Load(strVideos);

        XmlElement xeRoot = xdVideos.DocumentElement!;
        XmlElement xeVideo = xdVideos.CreateElement("video");
        xeRoot.AppendChild(xeVideo);

        xeRoot = xdVideos.DocumentElement!;

        xeVideo = xdVideos.CreateElement("title");
        XmlText txtvideo = xdVideos.CreateTextNode("The Day After Tomorrow");
        xeRoot.LastChild?.AppendChild(xeVideo);
        xeRoot.LastChild?.LastChild?.AppendChild(txtvideo);

        xeVideo = xdVideos.CreateElement("director");
        txtvideo = xdVideos.CreateTextNode("Roland Emmerich");
        xeRoot.LastChild?.AppendChild(xeVideo);
        xeRoot.LastChild?.LastChild?.AppendChild(txtvideo);

        xeVideo = xdVideos.CreateElement("length");
        txtvideo = xdVideos.CreateTextNode("124 Minutes");
        xeRoot.LastChild?.AppendChild(xeVideo);
        xeRoot.LastChild?.LastChild?.AppendChild(txtvideo);

        xeVideo = xdVideos.CreateElement("format");
        txtvideo = xdVideos.CreateTextNode("DVD");
        xeRoot.LastChild?.AppendChild(xeVideo);
        xeRoot.LastChild?.LastChild?.AppendChild(txtvideo);

        xeVideo = xdVideos.CreateElement("rating");
        txtvideo = xdVideos.CreateTextNode("PG-13");
        xeRoot.LastChild?.AppendChild(xeVideo);
        xeRoot.LastChild?.LastChild?.AppendChild(txtvideo);
    }
    else // if (!File.Exists(strVideos))
    {
        // Create the default XML structure
        xdVideos.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                          "<videos></videos>");
    }
            
    xdVideos.Save(strVideos);
}

This would produce:

<?xml version="1.0" encoding="utf-8"?>
<videos>
    <video>
        <title>The Distinguished Gentleman</title>
        <director>Jonathan Lynn</director>
        <length>112 Minutes</length>
        <format>DVD</format>
        <rating>R</rating>
    </video>
    <video>
        <title>Her Alibi</title>
        <director>Bruce Beresford</director>
        <length>94 Minutes</length>
        <format>DVD</format>
        <rating>PG-13</rating>
    </video>
    <video>
        <title>The Day After Tomorrow</title>
        <director>Roland Emmerich</director>
        <length>124 Minutes</length>
        <format>DVD</format>
        <rating>PG-13</rating>
    </video>
</videos>

Using the same approach, you can add children to children of children, and so on.

Locating an Element

Introduction

In some cases, you may want to perform an operation on an existing and particular node. For example, you may want to change the value of a node, you may want to add a new child node to an existing node, etc. Before taking any of these actions, you must be able to locate or identify the desired element.

Locating an element consists of looking for a particular node among the nodes. To do this, you must start somewhere. Obviously, the first node you can identify is the root. Once you get the root, you can then get a collection of its children. After getting a collection of the children of the root, you can locate a node in the collection. If the node you are looking for is a child of that first collection, you can then get a collection of the child nodes of that node and proceed.

Fortunately, the System.Xml namespace provides various means of looking for a node in an XML file.

Locating an Element Using its Index

Consider the following XML file named videos.xml:

<?xml version="1.0" encoding="utf-8"?>
<videos>
    <video>
        <title>The Distinguished Gentleman</title>
        <director>Jonathan Lynn</director>
        <length>112 Minutes</length>
        <format>DVD</format>
        <rating>R</rating>
    </video>
    <video>
        <title>Her Alibi</title>
        <director>Bruce Beresford</director>
        <length>94 Minutes</length>
        <format>DVD</format>
        <rating>PG-13</rating>
    </video>
    <video>
        <title>The Day After Tomorrow</title>
        <director>Roland Emmerich</director>
        <length>124 Minutes</length>
        <format>DVD</format>
        <rating>PG-13</rating>
    </video>
    <video>
        <title>Other People&#039;s Money</title>
        <director>Alan Brunstein</director>
        <length>114 Minutes</length>
        <format>VHS</format>
        <rating>PG-13</rating>
    </video>
</videos>

We know that the XmlNodeList class is equipped with both a method and an indexed property named Item. Their syntaxes are:

public abstract XmlNode Item(int index);
public virtual XmlNode this[int i] { get; }

These two members allow you to access an element based on its index. Here are examples:

using System.Xml;

namespace VideoCollection
{
    public partial class Exercise : Form
    {
        public Exercise()
        {
            InitializeComponent();
        }

        private void btnDocument_Click(object sender, EventArgs e)
        {
            XmlDocument xdVideos = new();
            string strVideos = "videos.xml";

            if (File.Exists(strVideos))
            {
                xdVideos.Load(strVideos);

                XmlElement xeRoot = xdVideos.DocumentElement!;
                XmlNodeList xnlVideos = xeRoot.ChildNodes;

                MessageBox.Show(xnlVideos[1]?.InnerText);

                MessageBox.Show(xnlVideos.Item(3)?.InnerXml);
            }
        }
    }
}

This would produce:

You can use this characteristic to locate a node. Because XML is very flexible with the names (you can have two child nodes that have the same name) and values (you can have two child nodes that have the same value) of nodes, when creating an XML file, it is your responsibility to create a scheme that would eventually allow you to uniquely identify each element.

Consider an XML document as follows:

<?xml version="1.0" encoding="utf-8"?>
<payrolls>
    <payroll>
	   <payroll-number>100001</payroll-number>
       <employee-number>946-824</employee-number>
       <time-worked>
            <monday>8.00</monday>
            <tuesday>9.50</tuesday>
            <friday>6.50</friday>
        </time-worked>
	</payroll>
	<payroll>
        <payroll-number>100002</payroll-number>
		<employee-number>408-315</employee-number>
		<time-worked>
			<saturday>9.00</saturday>
			<sunday>9.00</sunday>
		</time-worked>
	</payroll>
	<payroll>
		<payroll-number>100003</payroll-number>
		<employee-number>720-482</employee-number>
		<time-worked>
			<monday>7.00</monday>
			<wednesday>7.00</wednesday>
			<friday>7.00</friday>
		</time-worked>
	</payroll>
</payrolls>

We now know that the items of an XML document are organized as an array. Therefore, you can use a loop to get to each item. Here is an example that uses a do...while loop:

using System.Xml;

namespace PayrollPreparation
{
    public partial class Exercise : Form
    {
        public Exercise()
        {
            InitializeComponent();
        }

        private void Exercise_Load(object sender, EventArgs e)
        {
            XmlDocument xdPayrolls = new();
            string strPayrolls = @"C:\Payroll Preparation\Payroll.xml";

            if (File.Exists(strPayrolls) == true)
            {
                using (FileStream fsPayrolls = new FileStream(strPayrolls, FileMode.Open, FileAccess.Read))

                    xdPayrolls.Load(fsPayrolls);

                XmlElement xeRoot = xdPayrolls.DocumentElement!;
                XmlNodeList xnlPayrolls = xeRoot.ChildNodes;
                
                int i = 0;
                
                do
                {
                    MessageBox.Show(xnlPayrolls[i]?.InnerXml, "Payroll Preparation",
                                    MessageBoxButtons.OK, MessageBoxIcon.Information);
                    i++;
                } while (i <= xnlPayrolls.Count - 1);
            }
        }
    }
}

This would produce:

Payroll Preparation

Payroll Preparation

Payroll Preparation

In the same way, you can use a for loop. Here is an example:

using System.Xml;

namespace PayrollPreparation
{
    public partial class Exercise : Form
    {
        public Exercise()
        {
            InitializeComponent();
        }

        private void btnDocument_Click(object sender, EventArgs e)
        {
            XmlDocument xdPayrolls = new();
            string strVideos = @"E:\Payroll Preparation\Payroll.xml";

            if (File.Exists(strPayrolls) == true)
            {
                using (FileStream fsPayrolls = new FileStream(strPayrolls, FileMode.Open, FileAccess.Read))

                    xdPayrolls.Load(fsPayrolls);

                XmlNodeList xnlPayrolls = xdPayrolls.DocumentElement!.ChildNodes;

                for(int i = 0; i <= xnlPayrolls.Count - 1; i++)
                    MessageBox.Show(xnlPayrolls[i]?.InnerXml, "Payroll Preparation",
                                    MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }
    }
}

Enumerating the Child Elements of a Node

In the previous lesson, we saw how the XmlNodeList class starts:

public abstract class XmlNodeList : IEnumerable, 
				    IDisposable

As you can see, the XmlNodeList class implements the IEnumerable interface. As a result, you can use a foreach loop to visit each node of the list. Here is an example:

using System.Xml;

namespace PayrollPreparation
{
    public partial class Exercise : Form
    {
        public Exercise()
        {
            InitializeComponent();
        }

        private void btnDocument_Click(object sender, EventArgs e)
        {
            XmlDocument xdPayroll = new();
            string strPayrolls = @"E:\Payroll Preparation\Payroll.xml";

            if (File.Exists(strPayrolls) == true)
            {
                using (FileStream fsPayrolls = new FileStream(strPayrolls, FileMode.Open, FileAccess.Read))

                    xdVideos.Load(fsPayrolls);

                XmlNodeList xnlPayrolls = xdPayrolls.DocumentElement!.ChildNodes;

                foreach (XmlNode xnPayroll in xnlPayrolls)
                    MessageBox.Show(xnPayroll?.InnerXml);
            }
        }
    }
}

Accessing a Nested List

As we know already, an XmlNode object contains list of nodes represented by the ChildNodes property that is of type XmlNodeList. The XmlNodeList class contains an indexed property that in turn is of type XmlNode. The XmlNodeList class also contains a method named Item that returns an XmlNode object. This cycle of a property that contains a list where each item is the type of the property allows you to access a list of the children of a node. Based on this, if you have a node that has child nodes, if you want to get those child nodes, you can first get a list of the child nodes of that node and then use a loop to visite each child. Here is an example:

using System.Xml;

namespace PayrollPreparation
{
    public partial class Exercise : Form
    {
        public Exercise()
        {
            InitializeComponent();
        }

        private void btnDocument_Click(object sender, EventArgs e)
        {
            XmlDocument xdPayrolls = new();
            string strVideos = @"C:\Payroll Preparation\Payroll.xml";

            if (File.Exists(strVideos) == true)
            {
                using (FileStream fsVideos = new(strVideos, FileMode.Open, FileAccess.Read))

                    xdPayrolls.Load(fsPayrolls);

                XmlNodeList xnlPayrolls = xdPayrolls.DocumentElement!.ChildNodes;
                
                int i = 0;
                
                do
                {
                    XmlNodeList xnlTimesWorked = xnlPayrolls[i]!.ChildNodes;

                    int j = 0;

                    do
                    {
                        MessageBox.Show(xnlTimesWorked[j]?.InnerXml, "Payroll Preparation",
                                    MessageBoxButtons.OK, MessageBoxIcon.Information);
                        j++;
                    } while(j <= xnlTimesWorked.Count - 1);

                    i++;
                } while (i <= xnlPayrolls.Count - 1);
            }
        }
    }
}

This would produce:

Payroll Preparation Payroll Preparation

Payroll Preparation

Payroll Preparation Payroll Preparation

Payroll Preparation

Payroll Preparation Payroll Preparation

Payroll Preparation

In the same way, if some nodes have grand-children and further, you can keep going down the child nodes until you get to the level you want. Here is an example:

using System.Xml;

namespace PayrollPreparation
{
    public partial class Exercise : Form
    {
        public Exercise()
        {
            InitializeComponent();
        }

        private void btnDocument_Click(object sender, EventArgs e)
        {
            XmlDocument xdPayrolls = new();
            string strPayrolls = @"E:\Payroll Preparation\Payroll1.xml";

            if (File.Exists(strPayrolls) == true)
            {
                using (FileStream fsPayrolls = new FileStream(strPayrolls, FileMode.Open, FileAccess.Read))

                    xdPayrolls.Load(fsPayrolls);
                
                int i = 0;

                XmlNodeList xnlPayrolls = xdPayrolls.DocumentElement!.ChildNodes;
                
                do
                {
                    int j = 0;
                    XmlNodeList xnlWeekSummary = xnlPayrolls[i]!.ChildNodes;

                    do
                    {
                        int k = 0;
                        XmlNodeList xnlTimesWorked = xnlWeekSummary[j]!.ChildNodes;
                        
                        do
                        {
                            if(!string.IsNullOrEmpty(xnlTimesWorked[k]!.InnerXml))
                                MessageBox.Show(xnlTimesWorked[k]?.Name + ": " + xnlTimesWorked[k]?.InnerXml,
                                                "Payroll Preparation", MessageBoxButtons.OK, MessageBoxIcon.Information);

                            k++;
                        } while (k <= xnlTimesWorked.Count - 1);

                        j++;
                    } while(j <= xnlWeekSummary.Count - 1);

                    i++;
                } while (i <= xnlPayrolls.Count - 1);
            }
        }
    }
}

This would produce:

Payroll Preparation Payroll Preparation Payroll Preparation

 

Payroll Preparation Payroll Preparation Payroll Preparation

 

Payroll Preparation Payroll Preparation Payroll Preparation

Locating an Element Using its Name

To assist you with locating the first child node of a node, the XmlNode class is equipped with an indexed property (named Item) overloaded with two versions. One of the versions is declared as follows:

public virtual XmlElement this[string name] { get; }

This indexed property takes the name of a node as argument. After the property has been called, the parser checks the child nodes of the element on which the property was applied. If the parser finds a node with that name, it returns it as an XmlElement object. Here is an example:

private void btnDocument_Click(object sender, EventArgs e)
{
    XmlDocument xdVideos = new();
    string strVideos = "videos.xml";

    if (File.Exists(strVideos))
    {
        xdVideos.Load(strVideos);

        XmlNodeList xnlVideos = xdVideos.DocumentElement!.ChildNodes;

        MessageBox.Show(xnlVideos[1]!["director"]?.InnerText);

        MessageBox.Show(xnlVideos.Item(3)!["format"]?.InnerXml);
    }
}

Based on the videos.xml file we had earlier, this would produce:

If the node has more than one child with the same name, then it would return the first child with that name. You can use this characteristic to look for, or locate, an element.

Locating an Element Using a Tag Name

To assist you with finding a node, the XmlDocument class is equipped with a method named GetElementByTagName. It is overloaded with two versions. One of the syntaxes used is:

public virtual XmlNodeList GetElementsByTagName(string name);

This method takes as argument a string. The string must be the name of a node. If at least one node that holds that name exists in the document, this method returns a collection of the nodes with that name. If there is no node with that name, the collection is returned empty and there is no exception thrown.

Here is an example of calling the method:

using System.Xml;

namespace VideoCollection
{
    public partial class Exercise : Form
    {
        public Exercise()
        {
            InitializeComponent();
        }

        private void btnDocument_Click(object sender, EventArgs e)
        {
            XmlDocument xdVideos = new();
            string strVideos = @"E:\Videos Collection\Videos.xml";

            if (File.Exists(strVideos))
            {
                xdVideos.Load(strVideos);

                // Get a reference to the root node
                XmlElement xeRoot = xdVideos.DocumentElement!;

                // Create a list of nodes whose name is Title
                XmlNodeList xnlTitles = xdVideos.GetElementsByTagName("title");
            }
            else
                MessageBox.Show("The file " + strVideos + " was not found",
                                "Video Collection",
                                MessageBoxButtons.OK, MessageBoxIcon.Information);
        }
    }
}

Once you have a list of the nodes of a particular criterion, you can then act as you see fit. For example, you can look for a particular node that holds some text of your choice.


Previous Copyright © 2005-2023, FunctionX Saturday 03 December 2022 Next