LINQ to XML Programming Using Visual Basic.NET 2008

This article mainly focuses on manipulating XML documents using LINQ to XML, available in .NET Framework 3.5. In simple terms, we will design a Windows Form and do all CRUD operations against an existing XML document using LINQ to XML. We will also see how to use XPath in LINQ to XML.

Contributed by
Rating: 4 stars4 stars4 stars4 stars4 stars / 20
December 03, 2008
Rate this Article:
MEH MEH++


SEARCH ASP FREE
TOOLS YOU CAN USE

advertisement

To make the article simple, I designed a Windows Form as follows.


The following is the structure of the XML being followed in this article.


The explanation for the above XML (and basics of XML DOM/API in .NET Framework) is explained in my previous article titled "Visual Basic 2005 XML Programming using XML DOM" along with a sample XML document. To keep this article to the point, I will not repeat the same explanation here.

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 2008 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.

Loading/Searching XML document with LINQ to XML using Visual Basic 2008

The starting point to learn LINQ to 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 XDocument

doc = XDocument.Load(XMLDOCFILEPATH)


In the above code, I am creating a new XDocument object and loading XML into it. The XDocument class is completely different from the XMLDocument class. XDocument belongs to the "System.Linq" family whereas "XMLDocument" belongs to the "System.XML" family. Make sure that you import "System.Linq" before you work on "LINQ to XML" related classes.

Once the XML is loaded into the "XDocument" object, we can mold it to any kind of strongly typed object collection, simply by using "LINQ to XML Queries." For instance, the following would parse through all of the XML and give out a "List" based strongly typed collection with exactly the structure we need (Employee Information in this case):


Dim qList = From xe In doc.Descendants.Elements("Employee") _

Select New With { _

.ID = xe.Attribute("ID").Value, _

.Empno = xe.Element("Empno").Value, _

.Ename = xe.Element("Ename").Value, _

.Sal = xe.Element("Sal").Value, _

.Deptno = xe.Element("Deptno").Value _

}

Me.DataGridView1.DataSource = qList.ToList


If you observe the above code snippet, it is pretty similar to SQL querying. However, the above queries an XML Document!

Let us consider finding information on a single employee based on the employee number provided. The following is the code:


Dim qEmp = (From xe In doc.Descendants.Elements("Employee") _

Where xe.<Empno>.Value = "1010" _

Select New With { _

.ID = xe.@ID, _

.Empno = xe.<Empno>.Value, _

.Ename = xe.<Ename>.Value, _

.Sal = xe.<Sal>.Value, _

.Deptno = xe.<Deptno>.Value _

}).FirstOrDefault


In the above code, I wrote a different kind of query which directly uses the XML kind of syntax in Visual Basic itself. This is another great possibility in Visual Basic 2008. You can also observe that I injected a "Where" clause in the "From" statement.

Once the employee is found, we can retrieve information on its child elements as follows:


a = qEmp.SelectSingleNode("Ename").InnerText

b = qEmp.SelectSingleNode("Sal").InnerText

c = qEmp.SelectSingleNode("Deptno").InnerText

d = qEmp.GetAttribute("ID")


Adding, Updating and Deleting from an XML document using LINQ to XML

In previous section, we saw how to retrieve and search an XML document using "LINQ to XML." In this section we will manipulate an 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 qTargetDept As XElement = doc.Descendants.Elements("Department") _

.Where(Function(xe) xe.<Deptno>.Value = "30") _

.FirstOrDefault

If qTargetDept Is Nothing Then

MessageBox.Show("Department/EmployeeInfo not found")

Exit Sub

End If


Dim oEmp As New XElement("Employee")

oEmp.Add(New XAttribute("ID", "E20"))

oEmp.Add(New XElement("Empno", "4001"))

oEmp.Add(New XElement("Ename", "Winner"))

oEmp.Add(New XElement("Sal", "4500"))

oEmp.Add(New XElement("Deptno", "30"))


qTargetDept.Element("EmployeeInfo").Add(oEmp)


In the above code snippet, I am using the "XElement" class instead of the "XMLElement" class. "XElement" belongs to "System.Linq."

Similarly, we can also modify existing records using the following code:


Dim qEmp As XElement = doc.Descendants.Elements("Employee") _

.Where(Function(xe) xe.<Empno>.Value = "4001") _

.FirstOrDefault

qEmp.<Ename>.Value = "Winner2"

qEmp.<Sal>.Value = "5400"

qEmp.<Deptno>.Value = "30" 'this is not necessary

qEmp.@ID = "E40"


In the same manner, we can use the following code to delete an existing record:


Dim qEmp As XElement = doc.Descendants.Elements("Employee") _

.Where(Function(xe) xe.<Empno>.Value = "4001") _

.FirstOrDefault

qEmp.Remove()


Finally, we can save the XML document back to the file using the following code:


doc.Save(XMLDOCFILEPATH)


Make sure that "Save" is still supported in "XDocument" and it works in the same manner as "XMLDocument.Save" does.

Developing a complete form to work with LINQ to XML using Visual Basic 2008

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.Linq


Public Class Form1


Const XMLDOCFILEPATH As String = "....MyData.xml"



Dim doc As XDocument


Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

RefreshXDoc()

End Sub



Private Sub btnRefresh_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnRefresh.Click

Dim qList = From xe In doc.Descendants.Elements("Employee") _

Select New With { _

.ID = xe.Attribute("ID").Value, _

.Empno = xe.Element("Empno").Value, _

.Ename = xe.Element("Ename").Value, _

.Sal = xe.Element("Sal").Value, _

.Deptno = xe.Element("Deptno").Value _

}

Me.DataGridView1.DataSource = qList.ToList

End Sub


Private Sub btnSearch_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSearch.Click

Dim qEmp = (From xe In doc.Descendants.Elements("Employee") _

Where xe.<Empno>.Value = Me.txtEmpno.Text _

Select New With { _

.ID = xe.@ID, _

.Empno = xe.<Empno>.Value, _

.Ename = xe.<Ename>.Value, _

.Sal = xe.<Sal>.Value, _

.Deptno = xe.<Deptno>.Value _

}).FirstOrDefault

If qEmp Is Nothing Then

MessageBox.Show("Not found")

Exit Sub

End If


Me.txtEname.Text = qEmp.Ename

Me.txtSal.Text = qEmp.Sal

Me.txtDeptno.Text = qEmp.Deptno

Me.txtID.Text = qEmp.ID

End Sub


Private Sub btnClear_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnClear.Click

For Each c As Control In Me.Controls

If TypeOf c Is TextBox Then

CType(c, TextBox).Text = ""

End If

Next

End Sub


Private Sub btnAdd_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAdd.Click

Dim qTargetDept As XElement = doc.Descendants.Elements("Department") _

.Where(Function(xe) xe.<Deptno>.Value = Me.txtDeptno.Text) _

.FirstOrDefault

If qTargetDept Is Nothing Then

MessageBox.Show("Department/EmployeeInfo not found")

Exit Sub

End If


Dim oEmp As New XElement("Employee")

oEmp.Add(New XAttribute("ID", Me.txtID.Text))

oEmp.Add(New XElement("Empno", Me.txtEmpno.Text))

oEmp.Add(New XElement("Ename", Me.txtEname.Text))

oEmp.Add(New XElement("Sal", Me.txtSal.Text))

oEmp.Add(New XElement("Deptno", Me.txtDeptno.Text))


qTargetDept.Element("EmployeeInfo").Add(oEmp)

SaveXMLDoc()


MessageBox.Show("Added Successfully!")


End Sub


Developing a complete form to work with LINQ to XML using Visual Basic 2008: continued

The following continues from the previous section.


 

Private Sub btnDelete_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDelete.Click

Dim qEmp As XElement = doc.Descendants.Elements("Employee") _

.Where(Function(xe) xe.<Empno>.Value = Me.txtEmpno.Text) _

.FirstOrDefault

If qEmp Is Nothing Then

MessageBox.Show("Not found")

Exit Sub

End If


qEmp.Remove()

SaveXMLDoc()


MessageBox.Show("Deleted Successfully!")


End Sub


Private Sub btnUpdate_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnUpdate.Click

Dim qEmp As XElement = doc.Descendants.Elements("Employee") _

.Where(Function(xe) xe.<Empno>.Value = Me.txtEmpno.Text) _

.FirstOrDefault

If qEmp Is Nothing Then

MessageBox.Show("Not found")

Exit Sub

End If


If qEmp.<Deptno>.Value.Equals(Me.txtDeptno.Text) Then

''The following would simply modify and update the record

''However, it would not detach and attach to another dept branch (if dept is different)

qEmp.<Ename>.Value = Me.txtEname.Text

qEmp.<Sal>.Value = Me.txtSal.Text

qEmp.<Deptno>.Value = Me.txtDeptno.Text 'this is not necessary

qEmp.@ID = Me.txtID.Text

Else


'go to the Department node of provided department

Dim qTargetDept As XElement = doc.Descendants.Elements("Department") _

.Where(Function(xe) xe.<Deptno>.Value = Me.txtDeptno.Text) _

.FirstOrDefault

If qTargetDept Is Nothing Then

MessageBox.Show("Department/EmployeeInfo not found")

Exit Sub

End If


'remove node from current location

qEmp.Remove()

'adding node to new location

Dim oEmp As New XElement("Employee")

oEmp.Add(New XAttribute("ID", Me.txtID.Text))

oEmp.Add(New XElement("Empno", Me.txtEmpno.Text))

oEmp.Add(New XElement("Ename", Me.txtEname.Text))

oEmp.Add(New XElement("Sal", Me.txtSal.Text))

oEmp.Add(New XElement("Deptno", Me.txtDeptno.Text))


qTargetDept.Element("EmployeeInfo").Add(oEmp)


End If


SaveXMLDoc()

MessageBox.Show("Updated Successfully!")

End Sub


Private Sub RefreshXDoc()

doc = XDocument.Load(XMLDOCFILEPATH)

btnRefresh_Click(Nothing, Nothing)

End Sub


Private Sub SaveXMLDoc()

doc.Save(XMLDOCFILEPATH)

RefreshXDoc()

btnClear_Click(Nothing, Nothing)

End Sub


End Class

How to use XPath expressions in LINQ to XML

Most developers are familiar and comfortable with XPath. However, "LINQ to XML" does not support "XPath" directly. No method in "LINQ to XML" directly supports "XPath." However, Microsoft has provided an alternative way to use "XPath" expressions in "LINQ to XML" using "Extension Methods."

Let us consider that I would like to find all "Employee" elements in the document using XPath and want to use "LINQ to XML" to convert the result to strongly typed objects. This can be easily achieved using the following code:


Imports System.Linq

Imports System.Xml.Linq

Imports System.Xml.XPath.Extensions


Public Class Form2


Const XMLDOCFILEPATH As String = "....MyData.xml"


Private Sub btnRefresh_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnRefresh.Click

Dim doc As XDocument = XDocument.Load(XMLDOCFILEPATH)

Dim qList = From xe In doc.XPathSelectElements("//Employee") _

Select New With { _

.ID = xe.Attribute("ID").Value, _

.Empno = xe.Element("Empno").Value, _

.Ename = xe.Element("Ename").Value, _

.Sal = xe.Element("Sal").Value, _

.Deptno = xe.Element("Deptno").Value _

}

Me.DataGridView1.DataSource = qList.ToList

End Sub

End Class


You can also find a single employee information using XPath together with "LINQ to XML" as follows:


Private Sub btnSingleEmployee_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSingleEmployee.Click

Dim doc As XDocument = XDocument.Load(XMLDOCFILEPATH)

Dim qEmp = (From xe In doc.XPathSelectElements(String.Format("//Employee[Empno='{0}']", Me.txtEmpno.Text)) _

Select New With { _

.ID = xe.Attribute("ID").Value, _

.Empno = xe.Element("Empno").Value, _

.Ename = xe.Element("Ename").Value, _

.Sal = xe.Element("Sal").Value, _

.Deptno = xe.Element("Deptno").Value _

} _

).FirstOrDefault

If qEmp Is Nothing Then

MessageBox.Show("Not found")

Else

MessageBox.Show(String.Format("Name: {0}, Sal: {1}, Dept: {2}", qEmp.Ename, qEmp.Sal, qEmp.Deptno))

End If

End Sub


I hope you enjoyed the article and any suggestions, bugs, errors, enhancements etc. are highly appreciated at http://jagchat.spaces.live.com

blog comments powered by Disqus
VISUAL BASIC.NET ARTICLES

- Basic Form Properties and Modality in VB.NET
- Multiple Document Interfaces in Visual Basic
- Visual Basic for Beginners
- ASP.NET Image to PDF with VB.Net
- MySQL in ASP.NET: Mono using VB.NET
- AsyncFileUpload File Type and File Size Vali...
- Visual Studio: Adding Functionality and Style
- Clocks and Countdowns
- User-defined Functions using Visual Basic Ap...
- Understanding Object Binding in VBA
- Mastering the Message Box
- Testing a Windows Forms Application
- Using Visual Basic.NET Features to Code a Wi...
- Correcting Code in a Windows Forms Applicati...
- Write Readable Code and Comments for Windows...

ASP Web Hosting ASP.Net Web Hosting Windows Web Hosting
 
 
 

ASP Free Forums 
 RSS  Tutorials RSS
 RSS  Forums RSS
 RSS  All Feeds
Site Map 
Request Media Kit
Write For Us Get Paid 
Weekly Newsletter
 
Developer Updates  
Free Website Content 
Privacy Policy 
Support 


© 2003-2012 by Developer Shed. All rights reserved. DS Cluster 2 - Follow our Sitemap
Most Popular Topics
All ASP.Net Tutorials