Home

Operations on XML Elements

 

Adding a Simple Element

To programmatically create a new element, you can declare an XmlElement variable. To add the new element to the file, the XmlDocument class provides the CreateElement() method that is overloaded with three versions. One of the versions uses the following syntax:

public XmlElement CreateElement(string name);

Using this method, to create a new element, call it and pass it the name of the new element. If you want the element to have a value, the XmlDocument class is equipped with the CreateTextNode() method. 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. The calls to XmlDocument.CreateElement() and XmlDocument.CreateTextNode() allow you to initialize a new element. In order to actually add the new element, you must specify its position in the tree: whether it would be the first or the last node, whether you want to position it before or after a node of your choice. To support the positions of existing nodes, the XmlNode class, which is the ancestor of all XML nodes of the .NET Framework, provides various appropriate methods.

 One of these methods is AppendChild(), which is used to add an element as the last child of its parent. The syntax of the XmlNode.AppendChild() method is:

public virtual XmlNode AppendChild(XmlNode newChild);

Imagine you have a simple XML file that has only the root and one level of elements as follows:

<?xml version="1.0" encoding="utf-8"?>
<Holidays>
  <Holiday>New Year's Day</Holiday>
  <Holiday>Birthday of Martin Luther King, Jr.</Holiday>
  <Holiday>Washington's Birthday</Holiday>
</Holidays>

To add a new Holiday element to this file, based on the above discussions, you can use code as follows:

void BtnAddHolidayClick(object sender, System.EventArgs e)
{
	XmlDocument docXML = new XmlDocument();
	docXML.Load("Holidays.xml");

	XmlElement elmXML = docXML.CreateElement("Holiday");
	XmlText    txtXML = docXML.CreateTextNode("Memorial Day");
	docXML.DocumentElement.AppendChild(elmXML);
	docXML.DocumentElement.LastChild.AppendChild(txtXML);

	docXML.Save("Holidays.xml");
}

Practical Learning Practical Learning: Adding Elements

  1. To add a new form, in the Projects list, right-click CPAP2 -> Add -> New File
  2. In the Categories list, click C#. In the Templates list, click Form
  3. Set the File Name to NewMake.cs
     
  4. Click Create
  5. Click the Design tab below the Code Editor and design the form as follows:
     
    New Make
    Control Name Text Other Properties
    Label   New Car Make:  
    TextBox txtNewMake   Modifiers: Public
    Button btnOK OK DialogResult: OK
    Button btnCancel Cancel DialogResult: Cancel
    Form   New Make AcceptButton: btnOK
    CancelButton: btnCancel
    FormBorderStyle: FixedDialog
    MaximizeBox: False
    MinimizeBox: False
    ShowInTaskbar: False
    StartPosition: CenterScreen
  6. Display the first or main form Mainform.cs and click the Design tab. Add a new Button control to it
  7. Set its Name to btnNewMake and its Text to New Make
  8. Double-click the New Make button
  9. In the top section of the file, under the other using lines, type:
     
    using System.Xml;
  10. Implement its Click event as follows:
     
    private void BtnNewMakeClick(object sender, System.EventArgs e)
    {			
    	 // The new car make will come from the New Make dialog box
    	 NewMake frmMake = new NewMake();
    
    	 // Display the New Make dialog box and find out if the user clicked OK
    	 if( frmMake.ShowDialog() == DialogResult.OK )
    	 {
    		 string strNewMake = frmMake.txtNewMake.Text;
    					 
    		 // If the New Make string is empty, don't do anything
    		 if( strNewMake.Equals("") )
    			 return;
    
    		 // Open the Makes.xml file
    		 XmlDocument docXMLFile = new XmlDocument();
    		 docXMLFile.Load("Makes.xml");
    
    		 // Get the root node so we can explore its children
    		 XmlElement nodRoot     = docXMLFile.DocumentElement;
    		 // Store all the values of the elements in a string
    		 string allMyChildren   = nodRoot.InnerText;
    		 // Locate the new make among the values of the elements
    		 int indexLookForNewMake = allMyChildren.IndexOf(strNewMake);
    					 
    		 // If the car make exists already, don't add it
    		 if( indexLookForNewMake >= 0 )
    			 return;
    		 else
    		 {
    			 // If the car is not in the list already, add it as a Make element
    			 XmlElement elmXML = docXMLFile.CreateElement("Make");
    			 // Create its value using the string from the New Make dialog box
    		XmlText    txtXML = docXMLFile.CreateTextNode(frmMake.txtNewMake.Text);
    			 // Add the new element at the end of the file
    			 docXMLFile.DocumentElement.AppendChild(elmXML);
    			 // Specify its text
    			 docXMLFile.DocumentElement.LastChild.AppendChild(txtXML);
    
    			 // Save the file
    			 docXMLFile.Save("Makes.xml");
    		 }
    	 }
    }
  11. To add a new form, in the Projects list, right- click CPAP2 -> Add -> New File
  12. In the Categories list, click C#. In the Templates list, click Form
  13. Set the File Name to NewModel.cs and press Enter
  14. Design the form as follows:
     
    New Model
    Control Name Text Other Properties
    Label   New Car Model:  
    TextBox txtNewModel    
    Button btnOK OK DialogResult: OK
    Button btnCancel Cancel DialogResult: Cancel
    Form   New Car Model AcceptButton: btnOK
    CancelButton: btnCancel
    FormBorderStyle: FixedDialog
    MaximizeBox: False
    MinimizeBox: False
    ShowInTaskbar: False
    StartPosition: CenterScreen
  15. Display the first or main form (MainForm.cs [Design]) and add a new Button control to it
  16. Set its Name to btnNewModel and its Text to New Car Model
  17. Double-click the New Car Model button and implement its Click event as follows:
     
    private void BtnNewModelClick(object sender, System.EventArgs e)
    {			
    	 // The new car make will come from the New Make dialog box
    	 NewModel frmModel = new NewModel();
    
    	 // Display the New Make dialog box and find out if the user clicked OK
    	 if( frmModel.ShowDialog() == DialogResult.OK )
    	 {
    		 string strNewModel = frmModel.txtNewModel.Text;
    					 
    		 // If the New Make string is empty, don't do anything
    		 if( strNewModel.Equals("") )
    			 return;
    
    		 // Open the Makes.xml file
    		 XmlDocument docXMLFile = new XmlDocument();
    		 docXMLFile.Load("Models.xml");
    
    		 // Get the root node so we can explore its children
    		 XmlElement nodRoot     = docXMLFile.DocumentElement;
    		 // Store all the values of the elements in a string
    		 string allMyChildren   = nodRoot.InnerText;
    		 // Locate the new make among the values of the elements
    		 int indexLookForNewModel = allMyChildren.IndexOf(strNewModel);
    					 
    		 // If the car make exists already, don't add it
    		 if( indexLookForNewModel >= 0 )
    			 return;
    		 else
    		 {
    			 // If the car is not in the list already, add it as a Make element
    			 XmlElement elmXML = docXMLFile.CreateElement("Model");
    			 // Create its value using the string from the New Make dialog box
    		XmlText    txtXML = docXMLFile.CreateTextNode(frmModel.txtNewModel.Text);
    			 // Add the new element at the end of the file
    			 docXMLFile.DocumentElement.AppendChild(elmXML);
    			 // Specify its text
    			 docXMLFile.DocumentElement.LastChild.AppendChild(txtXML);
    
    			 // Save the file
    			 docXMLFile.Save("Models.xml");
    		 }
    	 }
    }
  18. Execute the application to test it
  19. Try adding one or two more car manufacturers like Toyota and Dodge
  20. Try adding an existing make to notice that it cannot be added twice
  21. Try adding one or more new car models such as Integra and 328I

Adding a Filled Child Element

The above Holidays.xml file had only one level under the root and no child element of the root had children. Suppose you have a file 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>
  </Video>
  <Video>
    <Title>Her Alibi</Title>
    <Director>Bruce Beresford</Director>
    <Length>94 Mins</Length>
    <Format>DVD</Format>
    <Rating>PG-13</Rating>
  </Video>
</Videos>

Imagine that you want to add a Video element. You have a choice of adding one, more, or all child elements of the Video node. To perform this operation, one solution you can use is to "build" all child elements of the Video element, then add the node as a whole. To support this technique, we saw earlier that the XmlNode.InnerXml property comprises a node, its markup, its children and their markup. This means that you can create the child nodes with their markup(s) as a string and assign that string to an XmlNode.InnerXml string. To do this, you would need the set version of the InnerXml property. It is declared as follows:

public virtual string InnerXml{get; set;}

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

private void Button1Click(object sender, System.EventArgs e)
{
	 XmlDocument docXML = new XmlDocument();
	 docXML.Load("Videos.xml");

	 XmlElement elmXML = docXML.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>";

	 elmXML.InnerXml = strNewVideo;
	 docXML.DocumentElement.AppendChild(elmXML);

	 docXML.Save("Videos.xml");
}

If you have an XML file with different levels and you want to add an element as a new child to a particular element, you can first locate that element. One way you can do this is to call the XmlDocument.GetElementByTagName() method. This method is overloaded with two versions. One of its versions has the following syntax:

public virtual XmlNodeList GetElementsByTagName(string name);

This method takes as argument the name of the element that you want to locate. If the method finds that element, it returns a list of all child nodes of that element as an XmlNodeList object. This XmlNodeList object represents a collection of nodes where each node can be located by its index through the ItemOf indexed property.

Practical Learning Practical Learning: Adding Elements

  1. Add a new Form and save it as NewPart
  2. Design the form as follows:
     
    New Part
    Control Name Text Other Properties
    Label   Year:  
    ComboBox cboYears   DropDownStyle: DropDownList
    Modifiers: Public
    Label   Make:  
    ComboBox cboMakes   DropDownStyle: DropDownList
    Modifiers: Public
    Button btnNewMake New Make  
    Label   Model:  
    ComboBox cboModels   DropDownStyle: DropDownList
    Modifiers: Public
    Button btnNewModel New Model  
    Label   Part Name:  
    TextBox txtPartName   Modifiers: Public
    Label   Unit Price:  
    TextBox txtUnitPrice 0.00 Modifiers: Public
    TextAlign: Right
    Label   Part #:  
    TextBox txtPartNumber 000000 Modifiers: Public
    TextAlign: Right
    Button btnAddPart Add Part  
    Button btnClose Close  
    Form     AcceptButton: btnAddPart
    CancelButton: btnClose
    MaximizeBox: False
    StartPosition: CenterScreen
  3. Double-click an unoccupied area of the form to access its Load event
  4. In the top section of the file, under the other using lines, type:
     
    using System.Xml;
  5. Implement the Load as follows:
     
    private void NewPartLoad(object sender, System.EventArgs e)
    {
    	// Fill the Year combo box with years from 1960 to the coming year
    	for(int i = DateTime.Now.Year+1; i >= 1960; i--)
    		this.cboYears.Items.Add(i.ToString());
    
    	// We will need a reference to the XML document
    	XmlDocument docXML = new XmlDocument();
    
    	// Open the Makes.xml file
    	docXML.Load("Makes.xml");
    
    	// Get a reference to the root node
    	XmlElement nodRoot = docXML.DocumentElement;
    	// Locate all nodes whose name is Make
    	XmlNodeList nodItems = nodRoot.GetElementsByTagName("Make");
    	// Retrieve the value of each Make node and put 
    	// that value in the Make combo box
    	for(int i = 0; i < nodItems.Count; i++)
    		this.cboMakes.Items.Add(nodItems[i].InnerXml);
    
    	// Open the Models.xml file
    	docXML.Load("Models.xml");
    
    	// Get a reference to the root node
    	nodRoot = docXML.DocumentElement;
    	// Locate all nodes whose name is Model
    	nodItems = nodRoot.GetElementsByTagName("Model");
    	// Retrieve the value of each Make node and put 
    	// that value in the Make combo box
    	for(int i = 0; i < nodItems.Count; i++)
    		this.cboModels.Items.Add(nodItems[i].InnerXml);
    
    	// We will generate a random number for the item
    	// To start, we will use the miliseconds as a seed
    	DateTime curTime = DateTime.Now;
    	int ms = curTime.Millisecond;
    
    	// Now we can generate a random number between 100000 and 999999
    	Random rndNumber = new Random(ms);
    	int next = rndNumber.Next(100000, 999999);
    	// Display the new number in the Part # text box
    	this.txtPartNumber.Text = next.ToString();
    
    	// Disable the OK button to indicate that the part is not ready
    	this.btnAddPart.Enabled = false;
    }
  6. Display the form again and double-click the New Make button
  7. Implement its Click event as follows:
     
    private void BtnNewMakeClick(object sender, System.EventArgs e)
    {
    	// The new car make will come from the New Make dialog box
    	 NewMake frmMake = new NewMake();
    
    	 // Display the New Make dialog box and find out if the user clicked OK
    	 if( frmMake.ShowDialog() == DialogResult.OK )
    	 {
    		 string strNewMake = frmMake.txtNewMake.Text;
    
    		 // If the New Make string is empty, don't do anything
    		 if( strNewMake.Equals("") )
    			 return;
    
    		 // Before adding the new make, check that it doesn't exist already
    		 if( this.cboMakes.FindStringExact(strNewMake) > 0 )
    			 return;
    
    		 // Now you can add it
    		 this.cboMakes.Items.Add(strNewMake);
    		 // The user likely wants this new item selected
    		 this.cboMakes.Text = strNewMake;
    
    		 // -- There are other ways you can add the new make to the Makes.xml file...
    		 // We are using the following approach because it allows different people
    		 // who are accessing the same file from different computers to update it 
    		 // without having to lock the file
    
    		 // Open the Makes.xml file
    		 XmlDocument docXMLFile = new XmlDocument();
    		 docXMLFile.Load("Makes.xml");
    
    		 // Get the root node so we can explore its children
    		 XmlElement nodRoot     = docXMLFile.DocumentElement;
    		 
    		// If the car is not in the list already, add it as a Make element
    		 XmlElement elmXML = docXMLFile.CreateElement("Make");
    		 // Create its value using the string from the New Make dialog box
    		 XmlText    txtXML = docXMLFile.CreateTextNode(strNewMake);
    		 // Add the new element at the end of the file
    		 docXMLFile.DocumentElement.AppendChild(elmXML);
    		 // Specify its text
    		 docXMLFile.DocumentElement.LastChild.AppendChild(txtXML);
    
    		 // Save the file
    		 docXMLFile.Save("Makes.xml");
    	}
    }
  8. Display the form again and double-click the New Model button
  9. Implement its Click event as follows:
     
    private void BtnNewModelClick(object sender, System.EventArgs e)
    {
    	 // The new car make will come from the New Make dialog box
    	 NewModel frmModel = new NewModel();
    
    	 // Display the New Make dialog box and find out if the user clicked OK
    	 if( frmModel.ShowDialog() == DialogResult.OK )
    	 {
    		 string strNewModel = frmModel.txtNewModel.Text;
    
    		 // If the New Make string is empty, don't do anything
    		 if( strNewModel.Equals("") )
    			 return;
    
    		 // Before adding the new make, check that it doesn't exist already
    		 if( this.cboModels.FindStringExact(strNewModel) > 0 )
    			 return;
    
    		 // Now you can add it
    		 this.cboModels.Items.Add(strNewModel);
    		 // The user likely wants this new item selected
    		 this.cboModels.Text = strNewModel;
    
    		 // -- There are other ways you can add the new make to the Makes.xml file...
    		 // We are using the following approach because it allows different people
    		 // who are accessing the same file from different computers to update it 
    		 // without having to lock the file
    
    		 XmlDocument docXMLFile = new XmlDocument();
    
    		 // Open the Makes.xml file
    		 docXMLFile = new XmlDocument();
    		 docXMLFile.Load("Models.xml");
    
    		 // Get the root node so we can explore its children
    		 XmlElement nodRoot     = docXMLFile.DocumentElement;
    		 
    		// If the model is not in the list already, add it as a Model element
    		 XmlElement elmXML = docXMLFile.CreateElement("Model");
    		 // Create its value using the string from the New Make dialog box
    		 XmlText txtXML = docXMLFile.CreateTextNode(strNewModel);
    		 // Add the new element at the end of the file
    		 docXMLFile.DocumentElement.AppendChild(elmXML);
    		 // Specify its text
    		 docXMLFile.DocumentElement.LastChild.AppendChild(txtXML);
    
    		 // Save the file
    		 docXMLFile.Save("Models.xml");
    	}
    }
  10. Return to the form and double-click the Part Name text box
  11. Implement its TextChanged event as follows:
     
    private void TxtPartNameTextChanged(object sender, System.EventArgs e)
    {
    	// If there is no part name, no need to add the item to the XML file
    	if( this.txtPartName.Text.Equals("") )
    		this.btnAddPart.Enabled = false;
    	else
    		this.btnAddPart.Enabled = true;
    }
  12. Return to the form and double-click the Unit Price text box
  13. Implement its TextChanged event as follows:
     
    private void TxtUnitPriceTextChanged(object sender, System.EventArgs e)
    {
    	// If the price is not specified, don't add the item to the XML file
    	if( this.txtUnitPrice.Text.Equals("") )
    		this.btnAddPart.Enabled = false;
    	else
    		this.btnAddPart.Enabled = true;
    }
  14. Return to the form and double-click the Part # text box
  15. Implement its TextChanged event as follows:
     
    private void TxtPartNumberTextChanged(object sender, System.EventArgs e)
    {
    	// Make sure that there is a Part Number for this item
    	// Otherwise, don't add the part to the XML file
    	try 
    	{
    		if( (this.txtPartNumber.Text.Equals("")) ||
    			(int.Parse(this.txtPartNumber.Text) < 100000) ||
    			(int.Parse(this.txtPartNumber.Text) > 999999) )
    			this.btnAddPart.Enabled = false;
    		else
    			this.btnAddPart.Enabled = true;
    	}
    	catch(FormatException )
    	{
    		MessageBox.Show("Only numbers are allowed");
    		this.txtPartNumber.Text = "";
    		this.txtPartNumber.Focus();
    	}
    }
  16. Display the first or main form (Form1.cs [Design]) and add a new Button control to it
  17. Set its Name to btnNewPart and its Text to New Part
     
  18. Double-click the New Car Model button and implement its Click event as follows:
     
    private void BtnNewPartClick(object sender, System.EventArgs e)
    {
    	 NewPart frmNewPart = new NewPart();
    
    	 if( frmNewPart.ShowDialog() == DialogResult.OK )
    	 {
    		string strPartNumber = frmNewPart.txtPartNumber.Text;
    		string strCarYear = frmNewPart.cboYears.Text;
    		string strMake = frmNewPart.cboMakes.Text;
    		string strModel = frmNewPart.cboModels.Text;
    		string strPartName = frmNewPart.txtPartName.Text;
    		string strUnitPrice = frmNewPart.txtUnitPrice.Text;
    
    		 if( strCarYear.Equals("") )
    			 return;
    		 if( strMake.Equals("") )
    			 return;
    		 if( strModel.Equals("") )
    			 return;
    
    		 XmlDocument docXML = new XmlDocument();
    		 docXML.Load("Parts.xml");
    
    		 XmlElement elmXML = docXML.CreateElement("Part");
    		 string strNewPart = "<PartNumber>" + strPartNumber + "</PartNumber>" +
    		                  "<CarYear>" + strCarYear + "</CarYear>" +
    			  "<Make>" + strMake + "</Make>" +
    			  "<Model>" + strModel + "</Model>" +
    			  "<PartName>" + strPartName + "</PartName>" +
    			  "<UnitPrice>" + strUnitPrice + "</UnitPrice>";
    
    		 elmXML.InnerXml = strNewPart;
    		 docXML.DocumentElement.AppendChild(elmXML);
    
    		 docXML.Save("Parts.xml");
    	 }
    }
    
    		private void btnClose_Click(object sender, System.EventArgs e)
    		{
    			Close();
    		}
  19. Execute the application to test it
  20. Try adding a new part to the Parts.xml file using the New Part dialog box accessed from the main form

Element Navigation

An XML tree navigation consists of visiting the various nodes of the file, for any necessary reason. One reason would be that you want to insert a new element at a specific position in the tree. Another would be that you want to check whether a certain node is already present in the tree.

As always, there are various ways you can perform an operation such as navigating a tree. To "scan" a file from top to bottom, thus visiting each type of node in the XML file, you can use the XmlTextReader class. This class is equipped with all types of properties and methods you would need.

If you want to navigate to a specific node in the tree, you can use the XmlDocument.GetElementByTagName() method that we used previously.

 

Previous Copyright 2005 FunctionX, Inc. Next