Inserting an Element

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 System.Xml.XmlNode? PrependChild(System.Xml.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.Xml;

public class Exercise : Form
{
    public Exercise()
    {
        InitializeComponent();
    }

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

        // Open the XML file
        xdVideos.Load(strVideos);

        // Create a new XML element
        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
        xdVideos.DocumentElement?.PrependChild(xeVideo);
        // Save the file
        xdVideos.Save(strVideos);
    }
}

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>

Adding an Element as a Last Child

Once again, consider 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>
    </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's Money</title>
        <director>Alan Brunstein</director>
        <length>114 Minutes</length>
        <format>VHS</format>
        <rating>PG-13</rating>
    </video>
</videos>

Imagine you want to add a list of actors of the Her Alibi video. The first action to take is to locate the video, which you can do by calling the XmlDocument.GetElementsByTagName() method applied to a collection of nodes whose names are video. From this list of nodes, you can look for the node whose value is "Her Alibi". Once you have found this element, get a reference to its parent. Then add the new node as a child its parent. This can be done as follows:

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

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

        // Now you can check each node of the list
        foreach (XmlNode? node in xnlTitles)
        {
            if (node?.InnerText == "Her Alibi")
            {
                // Create an element named Actors
                XmlElement xeActor = xdVideos.CreateElement("actors");
                XmlNode xeParent = node.ParentNode!;
                // Add a new element named Actors to it
                xeParent.AppendChild(xeActor);
                xdVideos.Save(strVideos);
            }
        }
    }
}

This would produce:

<?xml version="1.0" encoding="utf-8"?>
<videos>
    . . .
    <video>
        <title>Her Alibi</title>
        <director>Bruce Beresford</director>
        <length>94 Minutes</length>
        <format>DVD</format>
        <rating>PG-13</rating>
        <actors />
    </video>
    . . .
</videos>

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

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) == true)
            {
                using (FileStream fsVideos = new FileStream(strVideos, FileMode.Open))

                    xdVideos.Load(fsVideos);

                // 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? xnTitle 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 (xnTitle?.InnerText == "The Distinguished Gentleman")
                    {
                        // Create an element named Category
                        XmlElement xeCategory = xdVideos.CreateElement("category");
                        // Create the text of the new element
                        XmlText xtCatetory = xdVideos.CreateTextNode("Comedy");
                        // Get a reference to the parent of the node we have found
                        XmlNode xeParent = xnTitle.ParentNode!;
                        // Add the new element to the node we found
                        xeParent.AppendChild(xeCategory);
                        // Specify the text of the new node
                        xeParent.LastChild?.AppendChild(xtCatetory);
                        // Save the file
                        xdVideos.Save(strVideos);

                        // Stop searching
                        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>
  . . .
</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.Xml;

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

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

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

                // Create a list of nodes whose name is Title
                XmlNodeList xnlTitles = xdVideos.DocumentElement!.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 xeActors = xdVideos.CreateElement("actors");
                        // Get a reference to the parent of the node we have found
                        XmlNode? xnVideo = node.ParentNode;
                        // Add the new element to the node we found
                        xnVideo?.AppendChild(xeActors);

                        // Create an element as a child of the new element
                        // Specify its name as Actor
                        xeActors = 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
                        xnVideo?.LastChild?.AppendChild(xeActors);
                        // Specify the text of the new node
                        xnVideo?.LastChild?.LastChild?.AppendChild(txtActor);

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

                        xeActors = xdVideos.CreateElement("actor");
                        txtActor = xdVideos.CreateTextNode("Emmy Rossum");
                        xnVideo?.LastChild?.AppendChild(xeActors);
                        xnVideo?.LastChild?.LastChild?.AppendChild(txtActor);

                        xeActors = xdVideos.CreateElement("actor");
                        txtActor = xdVideos.CreateTextNode("Dash Mihok");
                        xnVideo?.LastChild?.AppendChild(xeActors);
                        xnVideo?.LastChild?.LastChild?.AppendChild(txtActor);

                        // Save the file
                        xdVideos.Save(strVideos);
                    }
                }
            }
            else
            {
                // 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 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>

Consider a document as follows:

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

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

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(strVideos);

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

                // Create a list of nodes whose name is Title
                XmlNodeList xnlTitles = xdVideos.DocumentElement!.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 xnVideo = node.ParentNode!;

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

                        // Visit each item of the collection
                        // looking for an element named Actors
                        foreach (XmlNode nodActor in lstActors)
                        {
                            // If you find an element named Actors
                            if (nodActor.Name == "actors")
                            {
                                // Create a new element named Actor
                                // Specify its name as Actor
                                XmlElement xeActor = 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
                                xnVideo?.LastChild?.AppendChild(xeActor);
                                // Specify the text of the new node
                                xnVideo?.LastChild?.LastChild?.AppendChild(txtActor);

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

                                xeActor = xdVideos.CreateElement("actor");
                                txtActor = xdVideos.CreateTextNode("William Daniels");
                                xnVideo?.LastChild?.AppendChild(xeActor);
                                xnVideo?.LastChild?.LastChild?.AppendChild(txtActor);

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

                                // Stop, in this example, we don't expect another Actors node
                                break;
                            }
                        }
                    }
                }
            }
            else
            {
                // 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>
        <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>

Inserting an Element Referencing Another Element

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 provides 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 above (that is, before) the director element whose name is Adrian Lyne. You can first get a list of videos. Inside each video, check the nodes and find out whether the video element 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.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) == true)
            {
                using (FileStream fsVideos = new FileStream(strVideos, FileMode.Open))

                    xdVideos.Load(fsVideos);

                // 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 xnlChildren = node.ChildNodes;

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

                            // Insert the new node below the Adrian Lyne node Director
                            node.InsertBefore(elmNew, xnDirector);

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

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

Inserting an Element After Another

Consider the following XML document from the previous lesson:

<?xml version="1.0" encoding="utf-8"?>
<payrolls>
    <weekly-pay>
        <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>
    </weekly-pay>
    <weekly-pay>
        <payroll-number>100002</payroll-number>
        <employee-number>408-315</employee-number>
        <time-worked>
            <saturday>9.00</saturday>
            <sunday>9.00</sunday>
        </time-worked>
    </weekly-pay>
    <weekly-pay>
        <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>
    </weekly-pay>
</payrolls>

To let you insert a 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);

When calling this method, pass an existing node as the first argument. Pass the new node as the second argument. 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 = @"C:\Payroll Preparation\Payroll.xml";

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

                    xdPayrolls.Load(fsPayrolls);

                XmlNodeList xnlPayrolls = xdPayrolls.GetElementsByTagName("payroll-number");

                foreach (XmlNode xnPayroll in xnlPayrolls)
                {
                    XmlNodeList xnlPayNumbers = xnPayroll.ChildNodes;

                    foreach (XmlNode xnNumber in xnlPayNumbers)
                    {
                        if (xnNumber.InnerText == "100002")
                        {
                            XmlElement xePaySummary = xdPayrolls.CreateElement("pay-summary");
                            xePaySummary.InnerXml = "<start-date>2023-01-02</start-date>" +
                                                    "<pay-frequency>Weekly</pay-frequency>";

                            xnPayroll.InsertAfter(xePaySummary, xnNumber);

                            xdPayrolls.Save(strPayrolls);

                            break;
                        }
                    }
                }
            }
        }
    }
}

The document would change as follows:

<?xml version="1.0" encoding="utf-8"?>
<payrolls>
    <weekly-pay>
        <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>
    </weekly-pay>
    <weekly-pay>
        <payroll-number>100002
            <pay-summary>
                <start-date>2023-01-02</start-date>
                <pay-frequency>Weekly</pay-frequency>
            </pay-summary>
        </payroll-number>
        <employee-number>408-315</employee-number>
        <time-worked>
            <saturday>9.00</saturday>
            <sunday>9.00</sunday>
        </time-worked>
    </weekly-pay>
    <weekly-pay>
        <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>
    </weekly-pay>
</payrolls>

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.

Updating an Element

Consider an XML document whose content is:

<?xml version="1.0" encoding="utf-8"?>
<videos>
    <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>

The .NET Framework implementation of XML provides various options to change the aspect, structure, or values, of an element. For example, you can use the same logic used in collection classes. This consists of locating a node and simply changing its value. Here is an example:

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 = @"C:\Videos Collection\Videos.xml";
            FileInfo fiVideos = new(strVideos);

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

                XmlNodeList xnlVideos = xdVideos.DocumentElement!.GetElementsByTagName("title");

                foreach (XmlNode xnVideo in xnlVideos)
                {
                    if (xnVideo.InnerText.Contains("Day After Tomorrow"))
                    {
                        xnVideo.ParentNode!.InnerXml = "<title>Day After Tomorrow(The)</title>" +
                                                       "<director>Roland Emmerich</director>" +
                                                       "<year>2004</year>" +
                                                       "<length>124 Minutes</length>" +
                                                       "<format>DVD</format>" +
                                                       "<rating>PG-13</rating>";
                        xdVideos.Save(strVideos);
                        break;
                    }
                }
            }
            else
            {
                // 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>Her Alibi</title>
        <director>Bruce Beresford</director>
        <length>94 Minutes</length>
        <format>DVD</format>
        <rating>PG-13</rating>
    </video>
    <video>
        <title>Day After Tomorrow(The)</title>
        <director>Roland Emmerich</director>
        <year>2004</year>
        <length>124</length>
        <format>DVD</format>
        <rating>PG-13</rating>
    </video>
</videos>

On the other hand, the XmlNode class is equipped with a method named ReplaceChild. Its syntax is:

public virtual System.Xml.XmlNode ReplaceChild (System.Xml.XmlNode newChild, System.Xml.XmlNode oldChild);

To use this method, first locate an element and get its reference. Then change the values or child nodes you want, and finally replace the original value with the new version. In reality, and as its name implies, it is not the primary purpose of this method to edit or update an element. The role of this method is to use one node in place of another.

Deleting Elements

Deleting an Element

If you have a node you don't want or don't need anymore, you can delete it. To let you delete a node, the XmlNode class provides a method named RemoveChild. Its syntax is:

public virtual XmlNode RemoveChild(XmlNode oldChild);

This method takes as argument the node to delete. If the node exists, it would be deleted and the method would return the node that was deleted. If the node does not exist, nothing would happen. To effectively use this method, you should first locate the particular node you want to delete. You can look for it using any of the techniques we have applied so far. Once you find the node, you can then delete it. Imagine you want to delete a node whose name is Director and whose value is Bruce Beresford. Here is an example of calling this method to perform the operation:

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

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

        // 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, get a list of its children
            XmlNodeList xnlChildren = node.ChildNodes;

            // Visit each child node
            foreach (XmlNode dir in xnlChildren)
            {
                // If the child node is Bruce Beresford
                if (dir.InnerText == "Bruce Beresford")
                {
                    node.RemoveChild(dir);

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

                    // Stop
                    break;
                }
            }
        }
    }
}

Clearing an Element of its Children

To let you delete all child nodes of a node, the XmlNode class provides a method named RemoveAll. Its syntax is:

public virtual void RemoveAll();

When called, this method will remove all child nodes, if any, of their parent node. Here is an example of calling it:

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(strVideos);

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

                XmlElement xeRoot = xdVideos.DocumentElement!;

                xeRoot.RemoveAll();
            }

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

This would produce:

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

XML and Object Oriented Programming

Introduction

The .NET Framework provides a rich collection of classes to perform all types of database operations on XML, including creating, locating, updating, and deleting nodes (these are referred to as CRUD (create, read, update, and delete) operations. Most of the necessary classes can be used to create local objects only used where needed. Still, at times, you may want to involve other classes in your application. As always, you can use built-in classes of the .NET Framework, you can create your own classes, or you can use all types of combinationss.

Fields and Properties

The .NET Framework contains many interfaces and classes such as XmlDocument, XmlNode, XmlElement, XmlNodeList. In a class, you can create a field or a property of most of those classes. Whether you declare a variable or create a property, make sure you appropriately initialize it. Here is an example of an XmlDocument property:

using System.Xml;

namespace ApplianceStore
{
    public partial class StoreInventory : Form
    {
        public XmlDocument? InventoryDocument { get; set; }

        public StoreInventory()
        {
            InitializeComponent();
        }

        private void StoreInventory_Load(object sender, EventArgs e)
        {
            InventoryDocument = new XmlDocument();
        }
    }
}

Remember that, in the same way, you can create a property of another type. In fact, since XmlNode is the abstractor ancestor to most XML classes, you can create a variable of it and initialize with the desired derived class. Here is an example:

using System.Xml;

namespace ApplianceStore
{
    public partial class StoreInventory : Form
    {
        public XmlNode? InventoryDocument { get; set; }

        public StoreInventory()
        {
            InitializeComponent();
        }

        private void StoreInventory_Load(object sender, EventArgs e)
        {
            InventoryDocument = new XmlDocument();
        }
    }
}

Either way, after creating the field or property, you can use it as appropriately as you see fit. Here is an example:

XML and Object Oriented Programming

XML and Object Oriented Programming

using System.Xml;

namespace ApplianceStore1
{
    public partial class StoreInventory : Form
    {
        FileInfo? fiAppliances;
        public XmlDocument? InventoryDocument { get; set; }
        string strAppliances = @"E:\Appliance Store\Appliances.xml";

        public StoreInventory()
        {
            InitializeComponent();
        }

        private void StoreInventory_Load(object sender, EventArgs e)
        {
            InventoryDocument = new XmlDocument();
            fiAppliances = new FileInfo(strAppliances);
        }

        private void btnSaveAppliance_Click(object sender, EventArgs e)
        {
            if (fiAppliances!.Exists)
            {
                InventoryDocument!.Load(fiAppliances.FullName);

                XmlElement xeAppliance = InventoryDocument.CreateElement("store-item");

                xeAppliance.InnerXml = "<item-number>" + txtItemNumber.Text + "</item-number>" +
                                       "<item-name>" + txtItemName.Text + "</item-name>" +
                                       "<capacity>" +
                                       "  <value>" + txtCapacityValue.Text + "</value>" +
                                       "  <unit-type>" + cbxUntsTypes.Text + "</unit-type>" +
                                       "</capacity>" +
                                       "<weight>" + txtWeight.Text + "</weight>" +
                                       "<dimensions>" +
                                       "  <depth>" + txtDepth.Text + "</depth>" +
                                       "  <width>" + txtWidth.Text + "</width>" +
                                       "  <height>" + txtHeight.Text + "</height>" +
                                       "</dimensions>" +
                                       "<unit-price>" + txtUnitPrice.Text + "</unit-price>";
                InventoryDocument.DocumentElement?.AppendChild(xeAppliance);
            }
            else // if (!File.Exists(strVideos))
            {
                // Create the default XML structure
                InventoryDocument!.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                                           "<ppliances></ppliances>");
            }

            InventoryDocument.Save(fiAppliances.FullName);
        }
    }
}

XML and Object Oriented Programming

This would produce:

<?xml version="1.0" encoding="utf-8"?>
<appliances>
  <store-item>
    <item-number>284759</item-number>
    <item-name>Farberware Countertop Microwave 1.1 Cu. Ft. 1000-Watt Compact Microwave Oven with LED lighting, Child lock, and Easy Clean Interior, Stainless</item-name>
    <capacity>
      <value>1.1</value>
      <unit-type>Cubic Feet</unit-type>
    </capacity>
    <weight>25.75</weight>
    <dimensions>
      <depth>16.54</depth>
      <width>20.2</width>
      <height>12.03</height>
    </dimensions>
    <unit-price>112.48</unit-price>
  </store-item>
</appliances>

Passing an Object as Argument

Most XML objects are from regular classes. This allows you to use them as parameters of functions or methods. If you create a parameter of one of those classes, make sure you use it following the rules of objects of interface, abstract, or regular classes. Here two examples of methods that use an XmlDocument argument:

using System.Xml;

namespace ApplianceStore1
{
    public partial class StoreInventory : Form
    {
        FileInfo? fiAppliances;
        string strAppliances = @"E:\Appliance Store\Appliances4.xml";

        public StoreInventory()
        {
            InitializeComponent();
        }

        private void StoreInventory_Load(object sender, EventArgs e)
        {
            fiAppliances = new FileInfo(strAppliances);
        }

        private void CreateDefaultDocument(XmlDocument doc, string name)
        {
            doc!.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                         "<" + name + "></" + name + ">");
        }
        
        private void AddAppliance(XmlDocument doc, string name)
        {
            XmlElement xeAppliance = doc.CreateElement(name);
            
            xeAppliance.InnerXml = "<item-number>" + txtItemNumber.Text + "</item-number>" +
                                   "<item-name>" + txtItemName.Text + "</item-name>" +
                                   "<capacity>" +
                                   "<value>" + txtCapacityValue.Text + "</value>" +
                                   "<unit-type>" + cbxUntsTypes.Text + "</unit-type>" +
                                   "</capacity>" +
                                   "<weight>" + txtWeight.Text + "</weight>" +
                                   "<dimensions>" +
                                   "<depth>" + txtDepth.Text + "</depth>" +
                                   "<width>" + txtWidth.Text + "</width>" +
                                   "<height>" + txtHeight.Text + "</height>" +
                                   "</dimensions>" +
                                   "<unit-price>" + txtUnitPrice.Text + "</unit-price>";

            doc.DocumentElement?.AppendChild(xeAppliance);

            doc.Save(fiAppliances!.FullName);
        }

        private void btnSaveAppliance_Click(object sender, EventArgs e)
        {
            var xdInventory = new XmlDocument();

            if (fiAppliances!.Exists)
            {
                xdInventory!.Load(fiAppliances.FullName);
            }
            else
            {
                CreateDefaultDocument(xdInventory, "appliances");
            }

            AddAppliance(xdInventory, "store-item");
            
            txtItemNumber.Text = txtItemName.Text = txtCapacityValue.Text = cbxUntsTypes.Text = 
                                 txtWeight.Text = txtDepth.Text = txtWidth.Text = txtHeight.Text = 
                                 txtUnitPrice.Text = string.Empty;
        }
    }
}

Returning an XML Object

In your application, you can create a function that produces an XML object. Of course, you have to decide which one of the various XML classes will handle the object. Other than that, everything else is done as in C#. Here is an example of a method that returns an XmlElement object:

using System.Xml;

namespace ApplianceStore1
{
    public partial class StoreInventory : Form
    {
        FileInfo? fiAppliances;
        public XmlDocument? InventoryDocument { get; set; }
        string strAppliances = @"E:\Appliance Store\Appliances4.xml";

        public StoreInventory()
        {
            InitializeComponent();
        }

        private void StoreInventory_Load(object sender, EventArgs e)
        {
            InventoryDocument = new XmlDocument();
            fiAppliances = new FileInfo(strAppliances);
        }

        private void CreateDefaultDocument(string name)
        {
            // Create the default XML structure
            InventoryDocument!.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                                       "<" + name + "></" + name + ">");
        }

        private XmlElement CreateAppliance()
        {
            XmlElement xeAppliance = InventoryDocument!.CreateElement("appliance");
            
            xeAppliance.InnerXml = "<item-number>" + txtItemNumber.Text + "</item-number>" +
                                   "<item-name>" + txtItemName.Text + "</item-name>" +
                                   "<capacity>" +
                                   "<value>" + txtCapacityValue.Text + "</value>" +
                                   "<unit-type>" + cbxUntsTypes.Text + "</unit-type>" +
                                   "</capacity>" +
                                   "<weight>" + txtWeight.Text + "</weight>" +
                                   "<dimensions>" +
                                   "<depth>" + txtDepth.Text + "</depth>" +
                                   "<width>" + txtWidth.Text + "</width>" +
                                   "<height>" + txtHeight.Text + "</height>" +
                                   "</dimensions>" +
                                   "<unit-price>" + txtUnitPrice.Text + "</unit-price>";

            return xeAppliance;
        }

        private void btnSaveAppliance_Click(object sender, EventArgs e)
        {
            if (fiAppliances!.Exists)
            {
                InventoryDocument!.Load(fiAppliances.FullName);
            }
            else
            {
                CreateDefaultDocument("appliances");
            }

            XmlElement xeAppliance = CreateAppliance();
            InventoryDocument!.DocumentElement?.AppendChild(xeAppliance);

            InventoryDocument.Save(fiAppliances!.FullName);
            
            txtItemNumber.Text = txtItemName.Text = txtCapacityValue.Text = cbxUntsTypes.Text = 
                                 txtWeight.Text = txtDepth.Text = txtWidth.Text = txtHeight.Text = 
                                 txtUnitPrice.Text = string.Empty;
        }
    }
}

Previous Copyright © 2005-2023, FunctionX Monday 06 December 2021 Next