Inserting an Element |
|
Locating an Element |
So far, we have been adding nodes quite randomly, that is, without much precision. In some cases, you may want to perform an operation on an existing and particular node. For example, you may want to change the value of a node, you may want to add a new child node to an existing node, etc. Before taking any of these actions, you must be able to locate or identify the desired element. To assist you with finding a node, the XmlDocument class is equipped with the GetElementByTagName() method which is overloaded with two versions. One of the syntaxes used is: |
public virtual XmlNodeList GetElementsByTagName(string name); This method takes as argument a string. The string must be the Name of a node. If at least one node that holds that name exists in the file, this method returns a collection of the nodes with that name. If there is no node with that name, the collection is returned empty and there is no exception. Here is an example of calling the method: using System; using System.IO; using System.Xml; namespace VideoCollection1 { class Program { static int Main(string[] args) { string strFilename = "Videos.xml"; XmlDocument xmlDoc = new XmlDocument(); if (File.Exists(strFilename)) { xmlDoc.Load(strFilename); // Get a reference to the root node XmlElement elmRoot = xmlDoc.DocumentElement; // Create a list of nodes whose name is Title XmlNodeList lstTitles = xmlDoc.GetElementsByTagName("Title"); // Now you can check each node of the list foreach(XmlNode node in lstTitles) { ; } } Console.WriteLine(); return 0; } } } Once you have a list of the nodes of a particular criterion, you can then act as you see fit. For example, For example, you can look for a particular node that holds a text of your choice. Here is an example: using System; using System.IO; using System.Xml; namespace VideoCollection1 { class Program { static int Main(string[] args) { string strFilename = "Videos.xml"; XmlDocument xmlDoc = new XmlDocument(); if (File.Exists(strFilename)) { xmlDoc.Load(strFilename); // Get a reference to the root node XmlElement elmRoot = xmlDoc.DocumentElement; //XmlNodeList lstVideos = xmlDoc.GetElementsByTagName("Video"); // Create a list of nodes whose name is Title XmlNodeList lstTitles = xmlDoc.GetElementsByTagName("Title"); // Now you can check each node of the list foreach(XmlNode node in lstTitles) { if (node.InnerText == "Her Alibi") { ; } } } Console.WriteLine(); return 0; } } }
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 Mins</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> 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 the LastChild object of its parent. This can be done as follows: using System; using System.IO; using System.Xml; namespace VideoCollection1 { class Program { static int Main(string[] args) { string strFilename = "Videos.xml"; XmlDocument xmlDoc = new XmlDocument(); if (File.Exists(strFilename)) { xmlDoc.Load(strFilename); // Get a reference to the root node XmlElement elmRoot = xmlDoc.DocumentElement; // Create a list of nodes whose name is Title XmlNodeList lstTitles = xmlDoc.GetElementsByTagName("Title"); // visit each node named Title foreach(XmlNode node in lstTitles) { // 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") { // Create an element named Actors XmlElement elmNew = xmlDoc.CreateElement("Actors"); XmlNode elmParent = node.ParentNode; // Add a new element named Actors to it elmParent.AppendChild(elmNew); xmlDoc.Save(strFilename); } } } Console.WriteLine(); return 0; } } } 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 Mins</Length> <Format>DVD</Format> <Rating>PG-13</Rating> <Actors /> </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> This code creates an empty element. If you want to create an element that includes a value, create its text and add that text as the LastChild of its parent. Here is an example: using System; using System.IO; using System.Xml; namespace VideoCollection1 { class Program { static int Main(string[] args) { string strFilename = "Videos.xml"; XmlDocument xmlDoc = new XmlDocument(); if (File.Exists(strFilename)) { xmlDoc.Load(strFilename); // Get a reference to the root node XmlElement elmRoot = xmlDoc.DocumentElement; // Create a list of nodes whose name is Title XmlNodeList lstTitles = xmlDoc.GetElementsByTagName("Title"); // visit each node named Title foreach(XmlNode node in lstTitles) { // 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 elmNew = xmlDoc.CreateElement("Category"); // Create the text of the new element XmlText txtCatetory = xmlDoc.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(elmNew); // Specify the text of the new node elmParent.LastChild.AppendChild(txtCatetory); // Save the file xmlDoc.Save(strFilename); } } } Console.WriteLine(); return 0; } } } 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 Mins</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 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; namespace VideoCollection1 { class Program { static int Main(string[] args) { string strFilename = "Videos.xml"; XmlDocument xmlDoc = new XmlDocument(); if (File.Exists(strFilename)) { xmlDoc.Load(strFilename); // Get a reference to the root node XmlElement elmRoot = xmlDoc.DocumentElement; // Create a list of nodes whose name is Title XmlNodeList lstTitles = xmlDoc.GetElementsByTagName("Title"); // visit each node named Title foreach(XmlNode node in lstTitles) { // 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 elmNew = xmlDoc.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(elmNew); // Create an element as a child of the new element // Specify its name as Actor elmNew = xmlDoc.CreateElement("Actor"); // Create the text of the new element XmlText txtActor = xmlDoc.CreateTextNode("Dennis Quaid"); // Add the new Actor element to the Actors node elmVideo.LastChild.AppendChild(elmNew); // Specify the text of the new node elmVideo.LastChild.LastChild.AppendChild(txtActor); // In the same way, add the other Actor nodes elmNew = xmlDoc.CreateElement("Actor"); txtActor = xmlDoc.CreateTextNode("Jake Gyllenhaal"); elmVideo.LastChild.AppendChild(elmNew); elmVideo.LastChild.LastChild.AppendChild(txtActor); elmNew = xmlDoc.CreateElement("Actor"); txtActor = xmlDoc.CreateTextNode("Emmy Rossum"); elmVideo.LastChild.AppendChild(elmNew); elmVideo.LastChild.LastChild.AppendChild(txtActor); elmNew = xmlDoc.CreateElement("Actor"); txtActor = xmlDoc.CreateTextNode("Dash Mihok"); elmVideo.LastChild.AppendChild(elmNew); elmVideo.LastChild.LastChild.AppendChild(txtActor); // Save the file xmlDoc.Save(strFilename); } } } Console.WriteLine(); return 0; } } } 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 Mins</Length> <Format>DVD</Format> <Rating>PG-13</Rating> <Actors /> </Video> <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: using System; using System.IO; using System.Xml; namespace VideoCollection1 { class Program { static int Main(string[] args) { string strFilename = "Videos.xml"; XmlDocument xmlDoc = new XmlDocument(); if (File.Exists(strFilename)) { xmlDoc.Load(strFilename); // Get a reference to the root node XmlElement elmRoot = xmlDoc.DocumentElement; // Create a list of nodes whose names are Title XmlNodeList lstTitles = xmlDoc.GetElementsByTagName("Title"); // visit each node named Title foreach(XmlNode node in lstTitles) { // 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 elmVideo = node.ParentNode; // Create a list of the child nodes of the Her alibi video XmlNodeList lstActors = elmVideo.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 elmNew = xmlDoc.CreateElement("Actor"); // Create the text of the new element XmlText txtActor = xmlDoc.CreateTextNode("Tom Selleck"); // Add the new Actor element to the Actors node elmVideo.LastChild.AppendChild(elmNew); // Specify the text of the new node elmVideo.LastChild.LastChild.AppendChild(txtActor); // Add other Actor nodes elmNew = xmlDoc.CreateElement("Actor"); txtActor = xmlDoc.CreateTextNode("Paulina Porizkova"); elmVideo.LastChild.AppendChild(elmNew); elmVideo.LastChild.LastChild.AppendChild(txtActor); elmNew = xmlDoc.CreateElement("Actor"); txtActor = xmlDoc.CreateTextNode("William Daniels"); elmVideo.LastChild.AppendChild(elmNew); elmVideo.LastChild.LastChild.AppendChild(txtActor); // Save the file xmlDoc.Save(strFilename); // Stop, in this example, we don't expect another Actors node break; } } } } } Console.WriteLine(); return 0; } } } 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 Mins</Length> <Format>DVD</Format> <Rating>PG-13</Rating> <Actors> <Actor>Tom Selleck</Actor> <Actor>Paulina Porizkova</Actor> <Actor>William Daniels</Actor> </Actors> </Video> <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>
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 the InsertBefore() method. 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>Her Alibi</Title> <Director>Bruce Beresford</Director> <Length>94 Mins</Length> <Format>DVD</Format> <Rating>PG-13</Rating> </Video> <Video> <Title>Fatal Attraction</Title> <Director>Adrian Lyne</Director> <Length>119 Minutes</Length> <Format>DVD</Format> <Rating>R</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> 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; using System.IO; using System.Xml; namespace VideoCollection1 { class Program { static int Main(string[] args) { string strFilename = "Videos.xml"; XmlDocument xmlDoc = new XmlDocument(); if (File.Exists(strFilename)) { xmlDoc.Load(strFilename); // Get a reference to the root node XmlElement elmRoot = xmlDoc.DocumentElement; // Create a list of the videos XmlNodeList lstVideos = xmlDoc.GetElementsByTagName("Video"); // visit each video foreach (XmlNode node in lstVideos) { // 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 elmNew = xmlDoc.CreateElement("Category"); // Specify the text of the new element elmNew.InnerText = "Drama"; // Insert the new node below the Adrian Lyne node Director node.InsertAfter(elmNew, dir); // Save the file xmlDoc.Save(strFilename); // Stop break; } } } } Console.WriteLine(); return 0; } } } 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 Mins</Length> <Format>DVD</Format> <Rating>PG-13</Rating> </Video> <Video> <Title>Fatal Attraction</Title> <Director>Adrian Lyne</Director> <Category>Drama</Category> <Length>119 Minutes</Length> <Format>DVD</Format> <Rating>R</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> In the same way, you can insert a new node after a child of a child (of a child of a child of a child) of any node. If you want to new node to be positioned after an existing child node, you can call the XmlNode.InsertAfter() method. Its syntax is: public virtual XmlNode InsertAfter(XmlNode newChild, XmlNode refChild);
If you have a node you don't want or don't need anymore in the file, you can delete it. To delete a node, the XmlNode class provides the RemoveChild() method. 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 it. If the node doesn't 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 logics 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: using System; using System.IO; using System.Xml; namespace VideoCollection1 { class Program { static int Main(string[] args) { string strFilename = "Videos.xml"; XmlDocument xmlDoc = new XmlDocument(); if (File.Exists(strFilename)) { xmlDoc.Load(strFilename); // Get a reference to the root node XmlElement elmRoot = xmlDoc.DocumentElement; // Create a list of the videos XmlNodeList lstVideos = xmlDoc.GetElementsByTagName("Video"); // visit each video foreach (XmlNode node in lstVideos) { // 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 Bruce Beresford if (dir.InnerText == "Bruce Beresford") { node.RemoveChild(dir); // Save the file xmlDoc.Save(strFilename); // Stop break; } } } } Console.WriteLine(); return 0; } } } To delete all child nodes of a node, you can call the XmlNode.RemoveAll() method. Its syntax is: public virtual void RemoveAll(); When called, this method will remove all child nodes, if any, of their parent node. |
|
||
Previous | Copyright © 2006-2016, FunctionX, Inc. | Next |
|