The Child Nodes of a Node

Introduction

As mentioned already, one node can be nested inside of another. A nested node is called a child of the nesting node. This also implies that a node can have as many children as necessary, making them child nodes of the parent node. Once again, consider our Videos.xml example:

<?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 Mins</length>
	<format>DVD</format>
	<rating>PG-13</rating>
  </video>
  <video>
	<title>Chalte Chalte</title>
	<director>Aziz Mirza</director>
	<length>145 Mins</length>
	<format>DVD</format>
	<rating>N/R</rating>
  </video>
</videos>

The title and the director nodes are children of the video node. The video node is the parent of both the title and the director nodes.

A Collection of XML Nodes

As you may know already, an XML document usually contains many nodes. To consider a collection of nodes, the .NET Framework provides a collection class named XmlNodeList. It starts as follows:

public abstract class XmlNodeList : IEnumerable, 
                                    IDisposable

Linking the Nodes

To manage the relationships among the nodes of an XML document, the .NET Framework provides a class named XmlLinkedNode:

public abstract class XmlLinkedNode : XmlNode

As a result, many classes derive from XmlLinkedNode. That's the case for the XmlElement class to which we were introduced in the previous lesson:

public class XmlElement : XmlLinkedNode

A Collection of Child Nodes

To support the child nodes of a particular node, the XmlNode class is equipped with a property named ChildNodes. That property is of type XmlNodeList. The property is declared as follows:

public virtual XmlNodeList ChildNodes { get; }

When this property is used, it produces an XmlNodeList list, which is a collection of all nodes that share the same parent. Each item in the collection is of type XmlNode. To give you the number of nodes on an XmlNodeList collection, the class is equipped with a property named Count. Here is an example of using it:

using System;
using System.IO;
using System.Xml;

public class Exercise
{
    public static int Main(string[] args)
    {
        XmlDocument xdVideos = new XmlDocument();
        string strVideosFile = @"C:\Videos Collection\Videos.xml";
        FileInfo fiVideos = new FileInfo(strVideosFile);

        Console.Title = "Videos Collection";
        Console.WriteLine("Videos Collection");
        Console.WriteLine("-----------------------------------");

        if (fiVideos.Exists == true)
        {
            xdVideos.Load(fiVideos.FullName);
            XmlElement xeVideo = xdVideos.DocumentElement;
            XmlNodeList xnlVideos = xeVideo.ChildNodes;

            Console.WriteLine("The root element contains {0} nodes.", xnlVideos.Count);
        }
        else
            Console.WriteLine("The file could not be located.");

        Console.WriteLine("===================================");
        return 10;
    }
}

This would produce:

Videos Collection
-----------------------------------
The root element contains 3 nodes.
===================================
Press any key to continue . . .

You can also use the Count property in a loop (while, do...while, or for) to visit the members of the collection.

Accessing a Node in a Collection

The children of a node, that is, the members of a ChildNodes property, or the members of an XmlNodeList collection, can be located each by an index. The first node has an index of 0, the second has an index of 1, and so on. To give you access to a node of the collection, the XmlNodeList class is equipped with an indexed property and a method named Item. Both produce the same result. For example, if a node has three children, to access the third, you can apply an index of 2 to its indexed property. Here is an example:

using System;
using System.IO;
using System.Xml;
using System.Windows.Forms;

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

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

            if (fiVideos.Exists == true)
            {
                xdVideos.Load(strVideosFile);
                XmlElement xeVideo = xdVideos.DocumentElement;
                XmlNodeList xnlVideos = xeVideo.ChildNodes;

                MessageBox.Show(string.Format("Inner Text: {0}", xnlVideos[2].InnerText), "Videos Collection");
            }
            else
                MessageBox.Show("The file could not be located.", "Videos Collection");
        }
    }
}

Accessing a Node in a Collection

You can also use the Item() method to get the same result. Using a loop (while, do...while, or for), you can access each node and display the values of its children as follows:

using System;
using System.IO;
using System.Xml;

public class Exercise
{
    public static int Main(string[] args)
    {
        XmlDocument xdVideos = new XmlDocument();
        string strVideosFile = @"C:\Videos Collection\Videos.xml";

        Console.Title = "Videos Collection";
        Console.WriteLine("Videos Collection");
        Console.WriteLine("-----------------------------------");

        if(File.Exists(strVideosFile))
        {
            xdVideos.Load(strVideosFile);
            XmlElement xeVideo = xdVideos.DocumentElement;
            XmlNodeList xnlVideos = xeVideo.ChildNodes;

            for (int i = 0; i < xnlVideos.Count; i++)
                Console.WriteLine("Inner Text: {0}", xnlVideos[i].InnerText);
        }
        else
            Console.WriteLine("The file could not be located.");

        Console.WriteLine("===================================");
        return 10;
    }
}

This would produce:

Videos Collection
-----------------------------------
Inner Text: The Distinguished GentlemanJonathan Lynn112 MinutesDVDR
Inner Text: Her AlibiBruce Beresford94 MinsDVDPG-13
Inner Text: Chalte ChalteAziz Mirza145 MinsDVDN/R
===================================
Press any key to continue . . .

Instead of using the indexed property, the XmlNodeList class implements the IEnumerable interface. This allows you to use a foreach loop to visit each node of the collection. Here is an example:

using System;
using System.IO;
using System.Xml;
using System.Windows.Forms;

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

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

            if (fiVideos.Exists == true)
            {
                xdVideos.Load(strVideosFile);
                XmlElement xeVideo = xdVideos.DocumentElement;
                XmlNodeList xnlVideos = xeVideo.ChildNodes;

                string strMessage = string.Empty;

                foreach (XmlNode node in xnlVideos)
                    strMessage += node.InnerText + Environment.NewLine;

                MessageBox.Show(strMessage, "Videos Collection");
            }
            else
                MessageBox.Show("The file could not be located.", "Videos Collection");
        }
    }
}

This would produce:

Accessing a Node in a Collection

To better manage and manipulate the nodes of a collection of nodes, you must be able to access the desired node. The XmlNode class combined with the XmlNodeList class provide various means of getting to a node and taking the appropriate actions.

The Parent of a Node

Not all nodes have children, obviously. For example, the title node of our Videos.xml file doesn't have children. To let you find out whether a node has children, the XmlNode class is equipped with a Boolean property named HasChildNodes

public virtual bool HasChildNodes { get; }

If a node is a child, to get its parent, you can access a property named ParentNode.

Fundamentals of Element Creation

Introduction

As seen so far, 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. 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 necessary properties and methods to perform the routine operations of an XML file, an element, or a node. The primary operation consists of creating a new element or 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 let you add an element to an XML document, the XmlNode class, which is the ancestor of all XML nodes of the .NET Framework, provides a method named AppendChild. Its syntax is:

public virtual XmlNode AppendChild(XmlNode newChild);

Calling this method an XmlElement object.

Adding a Value to the Root Node

Consider an XML file named Studies.xml that starts as follows:

<?xml version="1.0" encoding="utf-8" ?>
<studies></studies>

To let you add something, such as a value, to the root node the XmlDocument class provides a method named CreateTextNode. This method returns an XmlText value. The syntax of this method is:

public virtual XmlText CreateTextNode(string text);

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. Here is an example:

using System;
using System.IO;
using System.Xml;
using System.Windows.Forms;

namespace Studies
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void btnStudies_Click(object sender, EventArgs e)
        {
            XmlDocument xdStudies = new XmlDocument();
            string strXMLFile = @"C:\exercises\Studies.xml";

            xdStudies.Load(strXMLFile);

            XmlElement xeRoot = xdStudies.DocumentElement;

            XmlText xtNursing = xdStudies.CreateTextNode("Nursing Studies - Curriculum");

			// Add the child node to the root element
            xeRoot.AppendChild(xtNursing);

            xdStudies.Save(strXMLFile);
        }
    }
}

This would produce:

<?xml version="1.0" encoding="utf-8"?>
<studies>Nursing Studies - Curriculum</studies>

Adding an Empty Element to the Root

Consider an XML file named Videos.xml whose content is:

<?xml version="1.0" encoding="utf-8"?>
<videos />

To assist you with programmatically creating a new element, the XmlDocument class is equipped with 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 the name of the new element to it. For example, imagine you want to add a new Title element to the above document. You would start with code as follows:

string strVideosFile = Server.MapPath("Videos.xml");
System.Xml.XmlDocument xdVideos = new System.Xml.XmlDocument();

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

    System.Xml.XmlElement xeNewVideo = xdVideos.CreateElement("Title");
}

After calling the CreateElement method, call the XmlDocument.AppendChild() method to add the new element to the root node. Here is an example:

using System;
using System.IO;
using System.Xml;
using System.Windows.Forms;

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

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

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

                XmlElement xeRoot = xdVideos.DocumentElement;

                XmlElement xeNewVideo = xdVideos.CreateElement("title");

                xeRoot.AppendChild(xeNewVideo);
            }
            else
            {
                // Create the default XML structure
                xdVideos.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                                  "<videos></videos>");
            }

            xdVideos.Save(strVideosFile);
        }
    }
}

This would produce:

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

Adding a Full Element to the Root

Consider a starting XML file named Studies.xml whose content is:

<?xml version="1.0" encoding="utf-8"?>
<studies>
</studies>

We know (from the previous lesson) that the XmlNode class is equipped with the InnerXml property that holds a whole XML element. To add a new element to the root node, create the whole markup of the node. If necessary, include its child(ren) with its (their) markup(s) as a string and assign that string to an XmlNode.InnerXml string. Here is an example of using this property:

using System;
using System.IO;
using System.Xml;
using System.Windows.Forms;

namespace Studies
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void btnStudies_Click(object sender, EventArgs e)
        {
            XmlDocument xdStudies = new XmlDocument();
            string strStudies = @"C:\exercises\Studies.xml";

            if (File.Exists(strStudies))
            {
                using (FileStream fsStudies = new FileStream(strStudies,
                                                             FileMode.Open,
                                                             FileAccess.Read,
                                                             FileShare.Read))
                xdStudies.Load(fsStudies);

                XmlElement xeStudy = xdStudies.CreateElement("degrees");
                string strStudio   = "<undergraduate>Bachelor of Science in Nursing (BSN)</undergraduate>" +
                                     "<graduate>Master of Science in Nursing (MSN)</graduate>" +
                                     "<doctoral>Doctor of Nursing Practice (DNP)</doctoral>";

                xeVideo.InnerXml = strStudio;
                xdStudies.DocumentElement.AppendChild(xeStudy);

                using (FileStream fsStudies = new FileStream(strStudies,
                                                             FileMode.OpenOrCreate,
                                                             FileAccess.Write,
                                                             FileShare.Write))
                xdStudies.Save(fsStudies);
            }
        }
    }
}

This would produce:

<?xml version="1.0" encoding="utf-8"?>
<studies>
  <degrees>
    <undergraduate>Bachelor of Science in Nursing (BSN)</undergraduate>
    <graduate>Master of Science in Nursing (MSN)</graduate>
    <doctoral>Doctor of Nursing Practice (DNP)</doctoral>
  </degrees>
</studies>

Once again, consider a starting XML file named Studies.xml:

<?xml version="1.0" encoding="utf-8"?>
<studies>
</studies>

Adding an Element with Sub-Elements

You can create an element that has child elements that themselves have child elements. Here is an example:

using System;
using System.IO;
using System.Xml;
using System.Windows.Forms;

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

        private void btnStudies_Click(object sender, EventArgs e)
        {
            XmlDocument xdStudies = new XmlDocument();
            FileInfo fiStudies = new FileInfo(@"C:\exercises\Studies.xml");

            if (fiStudies.Exists == true)
            {
                using (FileStream fsStudies = new FileStream(fiStudies.FullName, FileMode.Open,
                                                             FileAccess.Read, FileShare.Read))
                {
                    xdStudies.Load(fsStudies);
                }

                XmlElement xeStudy = xdStudies.CreateElement("freshman");
                string strNursingProgram = "<fall-term><course>Human Anatomy &amp; Physiology I</course>" +
                                           "<course>Introduction to Practice-Based Research I</course>" +
                                           "<course>English Composition for Health Professions</course>" +
                                           "<course>Infant Psychology</course>" +
                                           "<course>Introduction to Expressive Sociology</course></fall-term>" +
                                           "<spring><course>Introduction to Statistics in Health Care</course>" +
                                           "<course>Human Anatomy &amp; Physiology II</course>" +
                                           "<course>Microbiology I</course></spring>";

                xeStudy.InnerXml = strNursingProgram;
                xdStudies.DocumentElement.AppendChild(xeStudy);

                using (FileStream fsStudies = new FileStream(fiStudies.FullName, FileMode.OpenOrCreate,
                                                             FileAccess.Write, FileShare.Write))
                {
                    xdStudies.Save(fsStudies);
                }
            }
        }
    }
}

This would produce:

<?xml version="1.0" encoding="utf-8"?>
<studies>
  <freshman>
    <fall-term>
      <course>Human Anatomy &amp; Physiology I</course>
      <course>Introduction to Practice-Based Research I</course>
      <course>English Composition for Health Professions</course>
      <course>Infant Psychology</course>
      <course>Introduction to Expressive Sociology</course>
    </fall-term>
    <spring>
      <course>Introduction to Statistics in Health Care</course>
      <course>Human Anatomy &amp; Physiology II</course>
      <course>Microbiology I</course>
    </spring>
  </freshman>
</studies>

Suppose that a document already contains one or more elements. Here is example of a 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>
</videos>

To add a new element as a child of the root, "build" one or all child elements, then assign the element to the XmlNode.InnerXml property. Here is an example:

using System;
using System.IO;
using System.Xml;
using System.Windows.Forms;

namespace VideosCollection
{
    public partial class Form1 : Form
    {
        public Form1() => InitializeComponent();

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

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

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

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

            xdVideos.Save(strVideosFile);
        }
    }
}

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>

The Last Child Node

Introduction

The child node that immediately precedes the end-tag of the parent node is called the last child. To give you access to the last child of a node, the XmlNode class is equipped with a property named LastChild. It is declared as follows:

public virtual XmlNode LastChild { get; }

Appending a Last Element

We saw that, to create a new element, the XmlDocument class provides the overloaded CreateElement() method. To add the new element to a file, you must specify its position in the tree. For example, you may want the new element to be positioned as the last node.

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, including the AppendChild method that we saw already. It is used to add an element as the last child of its parent. Normally, when you add an element to the root node, the new element is added as the last. An alternative is to call the LastChild property of the root node. As a result, the following code:

using System;
using System.IO;
using System.Xml;
using System.Windows.Forms;

namespace Studies
{
    public partial class Form1 : Form
    {
        public Form1() => InitializeComponent();

        private void btnVideosCollection_Click(object sender, EventArgs e)
        {
            XmlDocument xdStudies = new XmlDocument();
            string strStudies = @"C:\exercises\Studies.xml";
            FileInfo fiStudies = new FileInfo(strStudies);

            if( fiStudies.Exists == true )
            {
                using (FileStream fsStudies = new FileStream(fiStudies.FullName, FileMode.Open,
                                                             FileAccess.Read, FileShare.Read))
                {
                    xdStudies.Load(fsStudies);
                }

                XmlElement xeStudy = xdStudies.CreateElement("sophomore");
                string strNursingProgram = "<fall-term><course>Foundations of Pathology</course>" +
                                           "<course>Computer Databases I</course>" +
                                           "<course>Human Anatomy &amp; Physiology III</course>" +
                                           "<course>Infant Psychology II</course>" +
                                           "<course>Pharmacology I</course></fall-term>" +
                                           "<spring><course>Foundations of Clinical Nursing</course>" +
                                           "<course>Desktop Applications</course>" +
                                           "<course>Microbiology II</course></spring>";

                xeStudy.InnerXml = strNursingProgram;
                xdStudies.DocumentElement.AppendChild(xeStudy);

                using (FileStream fsStudies = new FileStream(strStudies, FileMode.OpenOrCreate,
                                                             FileAccess.Write, FileShare.Write))
                {
                    xdStudies.Save(fsStudies);
                }
            }
        }
    }
}

is the same as:

using System;
using System.IO;
using System.Xml;
using System.Windows.Forms;

namespace VideosCollection
{
    public partial class Form1 : Form
    {
        public Form1() => InitializeComponent();

        private void btnVideosCollection_Click(object sender, EventArgs e)
        {
            XmlDocument xdStudies = new XmlDocument();
            string strStudies = @"C:\exercises\Studies.xml";
            FileInfo fiStudies = new FileInfo(strStudies);

            if( fiStudies.Exists == true )
            {
                . . .

                xeStudy.InnerXml = strNursingProgram;
                xdStudies.DocumentElement.LastChild.AppendChild(xeStudy);

                using (FileStream fsStudies = new FileStream(strStudies, FileMode.OpenOrCreate,
                                                             FileAccess.Write, FileShare.Write))
                {
                    xdStudies.Save(fsStudies);
                }
            }
        }
    }
}

Adding an Element to the Last Child Node

Consider an XML file named Studies.xml that has the following content:

<?xml version="1.0" encoding="utf-8"?>
<studies>
  <nursing>
    
  </nursing>
  <mechanical-engineering>
    <freshman>
      <fall>
        <course>Physics I</course>
        <course>General Chemistry</course>
      </fall>
      <spring>
        <course>Integral Calculus</course>
        <course>Computing for Engineers</course>
      </spring>
    </freshman>
    <sophomore></sophomore>
  </mechanical-engineering> 
</studies>

To a new element as a child of the last node of a document, you can access the LastChild property of the LastChild of the root node. Of course, make sure you Call the AppendChild() method of the root node. Here is an example:

using System;
using System.IO;
using System.Xml;
using System.Windows.Forms;

namespace Studies
{
    public partial class Form1 : Form
    {
        public Form1() => InitializeComponent();

        private void btnStudies_Click(object sender, EventArgs e)
        {
            XmlDocument xdStudies = new XmlDocument();
            string strStudies = @"C:\exercises\Studies.xml";

            if (File.Exists(strStudies))
            {
                using (FileStream fsStudies = new FileStream(strStudies, FileMode.Open,
                                                             FileAccess.Read, FileShare.Read))
                {
                    xdStudies.Load(fsStudies);
                }

                XmlElement xeStudy = xdStudies.CreateElement("fall");
                string strNursingProgram = "<course>Multivariable Calculus I</course>" +
                                           "<course>Differential Equations I</course>" +
                                           "<course>Computing Techniques</course>" +
                                           "<course>Dynamics of Rigid Bodies</course>";

                xeStudy.InnerXml = strNursingProgram;
                xdStudies.DocumentElement.LastChild.LastChild.AppendChild(xeStudy);

                using (FileStream fsStudies = new FileStream(strStudies, FileMode.OpenOrCreate,
                                                             FileAccess.Write, FileShare.Write))
                {
                    xdStudies.Save(fsStudies);
                }
            }
        }
    }
}

This would produce:

<?xml version="1.0" encoding="utf-8"?>
<studies>
  <nursing>
  </nursing>
  <mechanical-engineering>
    <freshman>
      <fall>
        <course>Physics I</course>
        <course>General Chemistry</course>
      </fall>
      <spring>
        <course>Integral Calculus</course>
        <course>Computing for Engineers</course>
      </spring>
    </freshman>
    <sophomore>
      <fall>
        <course>Multivariable Calculus I</course>
        <course>Differential Equations I</course>
        <course>Computing Techniques</course>
        <course>Dynamics of Rigid Bodies</course>
      </fall>
    </sophomore>
  </mechanical-engineering>
</studies>

Consider the following 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:

using System;
using System.IO;
using System.Xml;
using System.Windows.Forms;

namespace VideosCollection
{
    public partial class Form1 : Form
    {
        public Form1() => InitializeComponent();

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

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

                XmlElement xeRoot = xdVideos.DocumentElement;
                XmlElement xeNewVideo = xdVideos.CreateElement("video");
                xeRoot.AppendChild(xeNewVideo);
            }
            else
            {
                xdVideos.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                                 "<videos></videos>");
            }

            xdVideos.Save(strVideosFile);
        }
    }
}

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 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:

using System;
using System.IO;
using System.Xml;
using System.Windows.Forms;

namespace VideosCollection
{
    public partial class Form1 : Form
    {
        public Form1() => InitializeComponent();

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

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

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

                xeRoot          = xdVideos.DocumentElement;

                xeNewVideo      = xdVideos.CreateElement("title");
                XmlText xtVideo = xdVideos.CreateTextNode("Her Alibi");

                xeRoot.LastChild.AppendChild(xeNewVideo);
                xeRoot.LastChild.LastChild.AppendChild(xtVideo);
            }
            else
            {
                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>
  </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 node 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 add 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 can be done as follows:

using System;
using System.IO;
using System.Xml;
using System.Windows.Forms;

namespace VideosCollection
{
    public partial class Form1 : Form
    {
        public Form1() => InitializeComponent();

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

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

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

                xeRoot = xdVideos.DocumentElement;

                xeNewVideo = xdVideos.CreateElement("title");
                XmlText xtVideo = xdVideos.CreateTextNode("The Day After Tomorrow");
                xeRoot.LastChild.AppendChild(xeNewVideo);
                xeRoot.LastChild.LastChild.AppendChild(xtVideo);

                xeNewVideo = xdVideos.CreateElement("director");
                xtVideo = xdVideos.CreateTextNode("Roland Emmerich");
                xeRoot.LastChild.AppendChild(xeNewVideo);
                xeRoot.LastChild.LastChild.AppendChild(xtVideo);

                xeNewVideo = xdVideos.CreateElement("length");
                xtVideo = xdVideos.CreateTextNode("124 Minutes");
                xeRoot.LastChild.AppendChild(xeNewVideo);
                xeRoot.LastChild.LastChild.AppendChild(xtVideo);

                xeNewVideo = xdVideos.CreateElement("format");
                xtVideo = xdVideos.CreateTextNode("DVD");
                xeRoot.LastChild.AppendChild(xeNewVideo);
                xeRoot.LastChild.LastChild.AppendChild(xtVideo);

                xeNewVideo = xdVideos.CreateElement("rating");
                xtVideo = xdVideos.CreateTextNode("PG-13");
                xeRoot.LastChild.AppendChild(xeNewVideo);
                xeRoot.LastChild.LastChild.AppendChild(xtVideo);
            }
            else
            {
                xdVideos.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                                  "<videos></videos>");
            }

            xdVideos.Save(strVideosFile);
        }
    }
}

 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.

This code creates an empty element. If you want to create an element that includes a value, create its text and add that text to the node. Here is an example:

using System;
using System.IO;
using System.Xml;
using System.Windows.Forms;

namespace VideosCollection
{
    public partial class Form1 : Form
    {
        public Form1() => InitializeComponent();

        private void btnVideosCollection_Click(object sender, EventArgs e)
        {
            FileInfo fiVideos = null;
            XmlDocument xdVideos = new XmlDocument();
            string strVideosFile = @"C:\Videos Collection\Videos.xml";

            fiVideos = new FileInfo(strVideosFile);

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

                // Create a list of nodes whose name is Title
                XmlNodeList xnlTitles = xdVideos.GetElementsByTagName("title");

                // Now you can check each node of the list
                foreach (XmlNode node in xnlTitles)
                {
                    // When you get to a node, look for the element's value
                    // If you find an element whose value is Her Alibi
                    if (node.InnerText == "The Distinguished Gentleman")
                    {
                        // Create an element named Category
                        XmlElement xeNewVideo = xdVideos.CreateElement("category");
                        // Create the text of the new element
                        XmlText txtCatetory = xdVideos.CreateTextNode("Comedy");
                        // Get a reference to the parent of the node we have found
                        XmlNode elmParent = node.ParentNode;
                        // Add the new element to the node we found
                        elmParent.AppendChild(xeNewVideo);
                        // Specify the text of the new node
                        elmParent.LastChild.AppendChild(txtCatetory);
                        // Save the file
                        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>
    <category>Comedy</category>
  </video>
  . . .
</videos>

Using the same approach combined with what we learned about adding an item, you can add a new element that itself has child nodes. Here is an example:

using System;
using System.IO;
using System.Xml;
using System.Windows.Forms;

namespace VideosCollection
{
    public partial class Form1 : Form
    {
        public Form1() => InitializeComponent();

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

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

                // 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");

                // Now you can check each node of the list
                foreach (XmlNode node in xnlTitles)
                {
                    // When you get to a node, look for the element's value
                    // If you find an element whose value is The Day After Tomorrow
                    if (node.InnerText == "The Day After Tomorrow")
                    {
                        // Create an element named Actors
                        XmlElement xeNewVideo = xdVideos.CreateElement("actors");
                        // Get a reference to the parent of the node we have found
                        XmlNode elmVideo = node.ParentNode;
                        // Add the new element to the node we found
                        elmVideo.AppendChild(xeNewVideo);

                        // Create an element as a child of the new element
                        // Specify its name as Actor
                        xeNewVideo = xdVideos.CreateElement("actor");
                        // Create the text of the new element
                        XmlText txtActor = xdVideos.CreateTextNode("Dennis Quaid");
                        // Add the new Actor element to the Actors node
                        elmVideo.LastChild.AppendChild(xeNewVideo);
                        // Specify the text of the new node
                        elmVideo.LastChild.LastChild.AppendChild(txtActor);

                        // In the same way, add the other Actor nodes
                        xeNewVideo = xdVideos.CreateElement("actor");
                        txtActor = xdVideos.CreateTextNode("Jake Gyllenhaal");
                        elmVideo.LastChild.AppendChild(xeNewVideo);
                        elmVideo.LastChild.LastChild.AppendChild(txtActor);

                        xeNewVideo = xdVideos.CreateElement("actor");
                        txtActor = xdVideos.CreateTextNode("Emmy Rossum");
                        elmVideo.LastChild.AppendChild(xeNewVideo);
                        elmVideo.LastChild.LastChild.AppendChild(txtActor);

                        xeNewVideo = xdVideos.CreateElement("actor");
                        txtActor = xdVideos.CreateTextNode("Dash Mihok");
                        elmVideo.LastChild.AppendChild(xeNewVideo);
                        elmVideo.LastChild.LastChild.AppendChild(txtActor);

                        // Save the file
                        xdVideos.Save(strVideosFile);
                    }
                }
            }
        }
    }
}

This would produce:

<?xml version="1.0" encoding="utf-8"?>
<videos>
  . . .
  <video>
    <title>The Day After Tomorrow</title>
    <director>Roland Emmerich</director>
    <length>124 Minutes</length>
    <format>DVD</format>
    <rating>PG-13</rating>
    <actors>
      <actor>Dennis Quaid</actor>
      <actor>Jake Gyllenhaal</actor>
      <actor>Emmy Rossum</actor>
      <actor>Dash Mihok</actor>
    </actors>
  </video>
</videos>

You can also insert one or more elements as children of an existing node after locating that node. Here is an example:

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>
    <category>Comedy</category>
  </video>
  <video>
    <title>Her Alibi</title>
    <director>Bruce Beresford</director>
    <length>94 Mins</length>
    <format>DVD</format>
    <rating>PG-13</rating>
    <actors />
  </video>
</videos>

Code Fragment:

using System;
using System.IO;
using System.Xml;
using System.Windows.Forms;

namespace VideosCollection
{
    public partial class Form1 : Form
    {
        public Form1() => InitializeComponent();

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

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

                // 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");

                // Now you can check each node of the list
                foreach (XmlNode node in xnlTitles)
                {
                    // When you get to a node, look for the element's value
                    // If you find an element whose value is Her Alibi
                    if (node.InnerText == "Her Alibi")
                    {
                        // Get a reference to the video node that is 
                        // the parent of the video titled Her Alibi
                        XmlNode xeVideo = node.ParentNode;

                        // Create a list of the child nodes of the Her alibi video
                        XmlNodeList xnlActors = xeVideo.ChildNodes;

                        // Visit each item of the collection
                        // looking for an element named Actors
                        foreach (XmlNode nodActor in xnlActors)
                        {
                            // If you find an element named Actors
                            if (nodActor.Name == "actors")
                            {
                                // Create a new element named Actor
                                // Specify its name as Actor
                                XmlElement xeNewVideo = xdVideos.CreateElement("actor");
                                // Create the text of the new element
                                XmlText txtActor = xdVideos.CreateTextNode("Tom Selleck");
                                // Add the new Actor element to the Actors node
                                xeVideo.LastChild.AppendChild(xeNewVideo);
                                // Specify the text of the new node
                                xeVideo.LastChild.LastChild.AppendChild(txtActor);

                                // Add other Actor nodes
                                xeNewVideo = xdVideos.CreateElement("actor");
                                txtActor = xdVideos.CreateTextNode("Paulina Porizkova");
                                xeVideo.LastChild.AppendChild(xeNewVideo);
                                xeVideo.LastChild.LastChild.AppendChild(txtActor);

                                xeNewVideo = xdVideos.CreateElement("actor");
                                txtActor = xdVideos.CreateTextNode("William Daniels");
                                xeVideo.LastChild.AppendChild(xeNewVideo);
                                xeVideo.LastChild.LastChild.AppendChild(txtActor);

                                // Save the file
                                xdVideos.Save(strVideosFile);

                                // Stop, in this example, we don't expect another Actors node
                                break;
                            }
                        }
                    }
                }
            }
        }
    }
}

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>
    <category>Comedy</category>
  </video>
  <video>
    <title>Her Alibi</title>
    <director>Bruce Beresford</director>
    <length>94 Minutes</length>
    <format>DVD</format>
    <rating>PG-13</rating>
    <actors>
      <actor>Tom Selleck</actor>
      <actor>Paulina Porizkova</actor>
      <actor>William Daniels</actor>
    </actors>
  </video>
</videos>

The First Child Node

Introduction

In a typical XML document, the first line is called the first child of the DOM. This would be:

<?xml version="1.0" encoding="utf-8"?>

After identifying or locating a node, the first node that immediately follows it is referred to as its first child.

Adding an Element as the First Child

Consider the following document saved in a 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>
</videos>

To let you add a new element and position it as the first in an XML document, the XmlNode class is equipped with a method named PrependChild. Its syntax is:

public virtual XmlNode PrependChild(XmlNode newChild);

This method receives an argument as an XmlNode object and adds it on top of the XML document. Here is an example of calling it:

using System;
using System.IO;
using System.Xml;
using System.Windows.Forms;

namespace VideosCollection
{
    public partial class Form1 : Form
    {
        public Form1() => InitializeComponent();

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

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

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

                // Specify the child nodes of the element
                xeVideo.InnerXml = "7243 4 92525 9 2" +
                                   "<title>Yanni - Tribute</title>" +
                                   "<director>George Veras</director>" +
                                   "<format>DVD</format>";
                // Add the new element as the first node in the document
                xeRoot.PrependChild(xeVideo);

                xdVideos.Save(strVideosFile);
            }
        }
    }
}

This would produce:

<?xml version="1.0" encoding="utf-8"?>
<videos>
  <Video>7243 4 92525 9 2
    <title>Yanni - Tribute</title>
    <director>George Veras</director>
    <format>DVD</format>
  </Video>
  <video>
    <title>The Distinguished Gentleman</title>
    <director>Jonathan Lynn</director>
    <length>112 Minutes</length>
    <format>DVD</format>
    <rating>R</rating>
  </video>
</videos>

Accessing a First Child Node

Consider the following videos.xml 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 Mins</length>
		<format>DVD</format>
		<rating>PG-13</rating>
    </video>
    <video>
		<title>Chalte Chalte</title>
		<director>Aziz Mirza</director>
		<length>145 Mins</length>
		<format>DVD</format>
		<rating>N/R</rating>
    </video>
</videos>

In our videos.xml file, the first child of the first video node is the <title>The Distinguished Gentleman</title> element. The first child of the second <video> node is <title>Her Alibi</title>.

To let you get the first child of a node, the XmlNode class provides a property named FirstChild. It is declared as follows:

public virtual XmlNode FirstChild { get; }

In the following example, every time the parser gets to a video node, it displays the value of it first child:

using System;
using System.IO;
using System.Xml;

public class Exercise
{
    public static int Main(string[] args)
    {
        XmlDocument xdVideos = new XmlDocument();
        string strVideosFile = @"C:\Videos Collection\Videos.xml";

        if (File.Exists(strVideosFile))
        {
            xdVideos.Load(strVideosFile);
            XmlElement xeVideo = xdVideos.DocumentElement;
            XmlNodeList xnlVideos = xeVideo.ChildNodes;

            foreach (XmlNode node in xnlVideos)
                Console.WriteLine("First Child Inner Text: {0}", node.FirstChild.InnerText);
        }

        Console.WriteLine("===================================");
        return 20;
    }
}

This would produce:

First Child Inner Text: The Distinguished Gentleman
First Child Inner Text: Her Alibi
First Child Inner Text: Chalte Chalte
===================================
Press any key to continue . . .

In this example, we started our parsing on the root node of the document. At times, you will need to consider only a particular node, such as the first child of a node. For example, you may want to use only the first child of the root. To get it, you can access the FirstChild property of the DocumentElement object of the DOM. Once you get that node, you can then do what you judge necessary.

Consider the following modification of the Videos.xml file:

<?xml version="1.0" encoding="utf-8" ?>
<Videos>
  <Video>
	<Title>The Distinguished Gentleman</Title>
	<Director>Jonathan Lynn</Director>
	<CastMembers>
	    <Actor>Eddie Murphy</Actor>
	    <Actor>Lane Smith</Actor>
	    <Actor>Sheryl Lee Ralph</Actor>
	    <Actor>Joe Don Baker</Actor>
	    <Actor>Victoria Rowell</Actor>
	</CastMembers>
	<Length>112 Minutes</Length>
	<Format>DVD</Format>
	<Rating>R</Rating>
  </Video>
  <Video>
	<Title>Her Alibi</Title>
	<Director>Bruce Beresford</Director>
	<Length>94 Mins</Length>
	<Format>DVD</Format>
	<Rating>PG-13</Rating>
  </Video>
  <Video>
	<Title>Chalte Chalte</Title>
	<Director>Aziz Mirza</Director>
	<Length>145 Mins</Length>
	<Format>DVD</Format>
	<Rating>N/R</Rating>
  </Video>
</Videos>

In the following example, only the values of the child nodes of the first child of the root are displayed:

using System;
using System.IO;
using System.Xml;

public class Exercise
{
    public static int Main(string[] args)
    {
        XmlDocument xdVideos = new XmlDocument();
        string strVideosFile = @"C:\Videos Collection\Videos.xml";

        if (File.Exists(strVideosFile))
        {
            xdVideos.Load(strVideosFile);
            // Locate the root node and 
            // get a reference to its first child
            XmlNode node = xdVideos.DocumentElement.FirstChild;
            // Create a list of the child nodes of 
            // the first node under the root
            XmlNodeList xnlVideos = node.ChildNodes;

            // Visit each node
            for (int i = 0; i < xnlVideos.Count; i++)
            {
                // Look for a node named CastMembers
                if (xnlVideos[i].Name == "CastMembers")
                {
                    // Once/if you find it,
                    // 1. Access its first child
                    // 2. Create a list of its child nodes
                    XmlNodeList xnlActors = xnlVideos[i].ChildNodes;

                    // Display the values of the nodes
                    for (int j = 0; j < xnlActors.Count; j++)
                        Console.WriteLine(string.Format("Inner Text: {0}", xnlActors[j].InnerText));
                }
            }
        }
        
        Console.WriteLine("===================================");
        return 10;
    }
}

This would produce:

Inner Text: Eddie Murphy
Inner Text: Lane Smith
Inner Text: Sheryl Lee Ralph
Inner Text: Joe Don Baker
Inner Text: Victoria Rowell
===================================
Press any key to continue . . .

The Content of the First Child Node

Remember that when using a loop (for or foreach) applied to an XmlNodeList collection, each node that you access is a complete XmlNode object and may have children. This means that you can further get the ChildNodes node of any node. Here is an example that primarily scans the nodes but looks for one whose name is CastMembers:

using System.IO;
using System.Xml;
using static System.Console;

public class Exercise
{
    public static int Main(string[] args)
    {
        XmlDocument xdVideos = new XmlDocument();
        string strVideosFile = @"C:\Videos Collection\Videos.xml";

        if (File.Exists(strVideosFile))
        {
            xdVideos.Load(strVideosFile);
            // Locate the root node and 
            // get a reference to its first child
            XmlNode node = xdVideos.DocumentElement.FirstChild;
            // Create a list of the child nodes of 
            // the first node under the root
            XmlNodeList xnlVideos = node.ChildNodes;

            // Visit each node
            for (int i = 0; i < xnlVideos.Count; i++)
            {
                // Look for a node named CastMembers
                if (xnlVideos[i].Name == "CastMembers")
                {
                    // Once/if you find it,
                    // 1. Access its first child
                    // 2. Create a list of its child nodes
                    XmlNodeList xnlActors = xnlVideos[i].ChildNodes;

                    // Display the values of the nodes
                    for (int j = 0; j < xnlActors.Count; j++)
                        WriteLine("Inner Text: {0}", xnlActors[j].InnerText);
                }
            }
        }
        
        WriteLine("===================================");
        return 10;
    }
}

We have learned that a node or a group of nodes can be nested inside of another node. When you get to a node, you may know or find out that it has children. You may then want to consider only the first child. Here is an example:

using System.IO;
using System.Xml;
using static System.Console;

public class Exercise
{
    public static int Main(string[] args)
    {
        string strVideosFile = @"C:\Videos Collection\Videos.xml";
        XmlDocument xdVideos = new XmlDocument();

        if (File.Exists(strVideosFile))
        {
            xdVideos.Load(strVideosFile);
            // Locate the root node and 
            // get a reference to its first child
            XmlNode node = xdVideos.DocumentElement.FirstChild;
            // Create a list of the child nodes of 
            // the first node under the root
            XmlNodeList xnlVideos = node.ChildNodes;

            // Visit each node
            for (int i = 0; i < xnlVideos.Count; i++)
            {
                // Look for a node named CastMembers
                if (xnlVideos[i].Name == "CastMembers")
                {
                    // Once/if you find it,
                    // 1. Access its first child
                    // 2. Create a list of its child nodes
                    XmlNodeList xnlActors = xnlVideos[i].FirstChild.ChildNodes;

                    // Display the value of its first child node
                    for (int j = 0; j < xnlActors.Count; j++)
                        WriteLine(string.Format("Actor: {0}", @xnlActors[j].InnerText));
                }
            }
        }
        
        WriteLine("===================================");
        return 10;
    }
}

This would produce:

Actor: Eddie Murphy
===================================
Press any key to continue . . .

The Siblings of a Node

Introduction

The child nodes that are nested in a parent node and share the same level are referred to as siblings.

The Next Sibling

To let you access the sibling of a node, the XmlNode class provides a property named NextSibling. It is declared as follows:

public virtual XmlNode NextSibling { get; }

Inserting an Element Before a Sibling

Instead of simply adding a new node at the end of child nodes, you can specify any other position you want. For example, you may want the new node to precede an existing child node. To support this operation, the XmlNode class is equipped with a method named InsertBefore. Its syntax is:

public virtual XmlNode InsertBefore(XmlNode newChild, XmlNode refChild);

The first argument of this method is the new node that will be added. The second argument is the sibling that will succeed the new node. Consider the following version of our 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>
      	<category>Comedy</category>
    </video>
    <video>
		<title>Fatal Attraction</title>
		<director>Adrian Lyne</director>
		<length>119 Minutes</length>
		<format>DVD</format>
		<rating>R</rating>
    </video>
</videos>

Imagine you want to create a new category element below the director element whose name is Adrian Lyne. You can first get a list of videos. Inside of each video, check the nodes and find out whether the video has a director node whose text is Adrian Lyne. Once you find that node, you can add the new element after it. Here is an example:

using System.IO;
using System.Xml;

public class Exercise
{
    public static int Main(string[] args)
    {
        string strVideosFile = @"C:\Videos Collection\Videos.xml";
        XmlDocument xdVideos = new XmlDocument();

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

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

            // Create a list of the videos
            XmlNodeList xnlVideos = xdVideos.GetElementsByTagName("video");

            // visit each video
            foreach (XmlNode node in xnlVideos)
            {
                // Within a video, create a list of its children
                XmlNodeList lstChildren = node.ChildNodes;

                // Visit each child node
                foreach (XmlNode dir in lstChildren)
                {
                    // If the child node is (a director and its name is) Adrian Lyne
                    if (dir.InnerText == "Adrian Lyne")
                    {
                        // Create an element named Category
                        XmlElement xeNewVideo = xdVideos.CreateElement("category");
                        // Specify the text of the new element
                        xeNewVideo.InnerText = "Drama";

                        // Insert the new node below the Adrian Lyne node Director
                        node.InsertAfter(xeNewVideo, dir);

                        // Save the file
                        xdVideos.Save(strVideosFile);

                        // Stop looking for the child node
                        break;
                    }
                }
            }
        }

        return 10203;
    }
}

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>
    <category>Comedy</category>
  </video>
  <video>
    <title>Fatal Attraction</title>
    <director>Adrian Lyne</director>
    <category>Drama</category>
    <length>119 Minutes</length>
    <format>DVD</format>
    <rating>R</rating>
  </video>
</videos>

In the same way, you can insert a new node after a child of a child (or of a child of a child of a child) of any node.

To let you position a new node after an existing child node, the XmlNode class is equipped with a method named InsertAfter. Its syntax is:

public virtual XmlNode InsertAfter(XmlNode newChild, XmlNode refChild);

Previous Copyright © 2005-2021, FunctionX Next