This article mainly focuses on manipulating XML documents using the XML API available in the .NET Framework. In simple terms, we will design a Windows Form and do all CRUD operations against an existing XML document.
To make the article simple, I designed a Windows Form as follows.
The entire source code for this article is available in the form of a free downloadable zip file. The solution was developed using Microsoft Visual Studio 2005 on Microsoft Windows Server 2003 Standard Edition (with SP3). I didn't really test it in any other environment. I request that you post in the discussion area if you have any problems in execution.
Understanding the structure of the sample XML document
Before we start manipulating the XML document, we should fully understand the content and structure of the XML document on which we are working. Let us try to understand the structure of the sample XML document from the following figure.
The above would read something like the following:
A company has a few departments. Each department has information about its number, name, location and a few employees working in the same. Similarly, all employee information is maintained with an ID, number, name, salary and department number.
The starting point (say root) of the document is company (or "CompanyInfo"). All of the departments in the company are maintained (encapsulated) in a single unit named "DepartmentInfo." The "DepartmentInfo" contains a group of departments. Each piece of department information starts with a "Department" tag (or element). Every "Department" also has an "ID" as attribute and a group of elements directly beneath it. The tags "Deptno," "Dname," "Location" and "EmployeeInfo" are direct descendants of the "Department" tag. The "EmployeeInfo" contains a group of employees (along with their information). Every employee and his information ("Empno," "Ename," "Sal" and "Deptno") is embedded in a single parent element named "Employee," which is again a direct descendant to the "EmployeeInfo" element.
Now that we understand the structure of the sample XML document (from the previous section), we need to have some sample XML data to work with .NET.
The following is the XML source used as a sample in the .NET application. It follows the same structure as explained in the previous section. I named it MyXML.xml.
The starting point for learning XML programming is to load the XML document into an object. Let us look at that:
Const XMLDOCFILEPATH As String = "....MyData.xml"
Dim doc As XmlDocument
doc = New XmlDocument
doc.Load(XMLDOCFILEPATH)
In the above code, I am creating a new XMLDocument object and loading XML into it. Make sure that you import "System.XML" before you work on XML-related classes.
Once the XML is loaded into the "XMLDocument" object, we can mold it to any kind of object. For instance, we can create a strongly typed data table using the following code:
Dim nEmps As XmlNodeList = doc.SelectNodes("//Employee")
Dim dt As New DataTable
dt.Columns.Add("ID")
dt.Columns.Add("Empno")
dt.Columns.Add("Ename")
dt.Columns.Add("Sal")
dt.Columns.Add("Deptno")
For Each nEmp As XmlElement In nEmps
Dim dr As DataRow = dt.NewRow
dr("ID") = nEmp.GetAttribute("ID")
dr("Empno") = nEmp.ChildNodes(0).InnerText
dr("Ename") = nEmp.ChildNodes(1).InnerText
dr("Sal") = nEmp.ChildNodes(2).InnerText
dr("Deptno") = nEmp.ChildNodes(3).InnerText
dt.Rows.Add(dr)
Next
The alternative way to achieve something similar to the above is by using "Dataset.ReadXml."
If you observe the above code snippet, I used "//Employee" to retrieve only "Employee" elements (along with their child elements). "//Employee" is an XPath expression. XPath is a simple "search" kind of technology for XML. It has its own operators and syntax. By using XPath expressions we can retrieve/find any part of the provided XML.
Let us consider finding single employee information (using XPath) based on the employee number provided. The following is the code:
Dim nEmp As XmlElement = doc.SelectSingleNode("//Employee[Empno='1007']")
Once the employee is found, we can retrieve information about its child elements as follows:
In the previous section, we have seen how to retrieve and search an XML document using XML DOM. In this section we will manipulate the XML document with Add, Update and Delete operations.
Let us consider adding a new employee to department 30. The following is the sample code:
Dim nEmpInfo As XmlNode = doc.SelectSingleNode("//Department[Deptno='30']/EmployeeInfo")
Dim nEmployee As XmlNode = doc.CreateElement("Employee")
Dim nEmpno As XmlNode = doc.CreateElement("Empno")
Dim nEname As XmlNode = doc.CreateElement("Ename")
Dim nSal As XmlNode = doc.CreateElement("Sal")
Dim nDeptno As XmlNode = doc.CreateElement("Deptno")
Dim aID As XmlAttribute = doc.CreateAttribute("ID")
'assign values to elements
nEmpno.InnerText = "4001"
nEname.InnerText = "Winner"
nSal.InnerText = "4500"
nDeptno.InnerText = "30"
aID.InnerText = "E20"
'form the node structure
With nEmployee
.Attributes.Append(aID)
.AppendChild(nEmpno)
.AppendChild(nEname)
.AppendChild(nSal)
.AppendChild(nDeptno)
End With
nEmpInfo.AppendChild(nEmployee)
Similarly, we can also modify existing record information using the following code:
Dim nEmp As XmlElement = doc.SelectSingleNode("//Employee[Empno='4001']")
To demonstrate all of the previous concepts, I designed a Windows form for CRUD operations as shown in Fig 1. The following is the code developed for the form:
Imports System.Xml
Public Class Form1
Const XMLDOCFILEPATH As String = "....MyData.xml"
Dim doc As New XmlDocument
Private Sub btnSearch_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSearch.Click
Dim nEmp As XmlElement = doc.SelectSingleNode(String.Format("//Employee[Empno='{0}']", Me.txtEmpno.Text))
nEmp.SelectSingleNode("Deptno").InnerText = Me.txtDeptno.Text 'this is not necessary
nEmp.SetAttribute("ID", Me.txtID.Text)
Else
'go to the EmployeeInfo node of provided department
Dim nTargetEmpInfo As XmlNode = doc.SelectSingleNode(String.Format("//Department[Deptno='{0}']/EmployeeInfo", Me.txtDeptno.Text))
If nTargetEmpInfo Is Nothing Then
MessageBox.Show("Department/EmployeeInfo not found")
Exit Sub
End If
'remove node from current location
Dim nSourceEmpInfo As XmlElement = nEmp.SelectSingleNode("ancestor::EmployeeInfo")
nSourceEmpInfo.RemoveChild(nEmp)
'adding node to new location
'create elements of node structure
Dim nEmployee As XmlNode = doc.CreateElement("Employee")
Dim nEmpno As XmlNode = doc.CreateElement("Empno")
Dim nEname As XmlNode = doc.CreateElement("Ename")
Dim nSal As XmlNode = doc.CreateElement("Sal")
Dim nDeptno As XmlNode = doc.CreateElement("Deptno")
Dim aID As XmlAttribute = doc.CreateAttribute("ID")
'assign values to elements
nEmpno.InnerText = Me.txtEmpno.Text
nEname.InnerText = Me.txtEname.Text
nSal.InnerText = Me.txtSal.Text
nDeptno.InnerText = Me.txtDeptno.Text
aID.InnerText = Me.txtID.Text
'form the node structure
With nEmployee
.Attributes.Append(aID)
.AppendChild(nEmpno)
.AppendChild(nEname)
.AppendChild(nSal)
.AppendChild(nDeptno)
End With
nTargetEmpInfo.AppendChild(nEmployee)
End If
SaveXMLDoc()
MessageBox.Show("Updated Successfully!")
End Sub
Private Sub btnDelete_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDelete.Click
Dim nEmp As XmlElement = doc.SelectSingleNode(String.Format("//Employee[Empno='{0}']", Me.txtEmpno.Text))
If nEmp Is Nothing Then
MessageBox.Show("Not found")
Exit Sub
End If
Dim nEmpInfo As XmlElement = nEmp.SelectSingleNode("ancestor::EmployeeInfo")
nEmpInfo.RemoveChild(nEmp)
SaveXMLDoc()
MessageBox.Show("Deleted Successfully!")
End Sub
Private Sub btnRefresh_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnRefresh.Click
Dim nEmps As XmlNodeList = doc.SelectNodes("//Employee")
Dim dt As New DataTable
dt.Columns.Add("ID")
dt.Columns.Add("Empno")
dt.Columns.Add("Ename")
dt.Columns.Add("Sal")
dt.Columns.Add("Deptno")
For Each nEmp As XmlElement In nEmps
Dim dr As DataRow = dt.NewRow
dr("ID") = nEmp.GetAttribute("ID")
dr("Empno") = nEmp.ChildNodes(0).InnerText
dr("Ename") = nEmp.ChildNodes(1).InnerText
dr("Sal") = nEmp.ChildNodes(2).InnerText
dr("Deptno") = nEmp.ChildNodes(3).InnerText
dt.Rows.Add(dr)
Next
Me.DataGridView1.DataSource = dt
End Sub
End Class
My next upcoming article will focus on LINQ to XML. I hope you enjoyed the article and any suggestions, bugs, errors, enhancements etc. are highly appreciated at http://jagchat.spaces.live.com