DotNetCurry Logo

Some Common Operations using LINQ To XML - Part II

Posted by: Suprotim Agarwal , on 11/2/2008, in Category LINQ
Views: 33014
Abstract: In this article, we will explore some common ‘How Do I’ kind of examples using LINQ to XML. This article is the Part II of the 3-part LINQ to XML series.
Some Common Operations using LINQ To XML - Part II
 
In this article, we will explore some common ‘How Do I’ kind of examples using LINQ to XML. This article is the Part II of the 3-part LINQ to XML series. I hope you have read the previous article Some Common Operations using LINQ To XML - Part I. I assume you are familiar with LINQ. If not, you can start off with LINQ to XML by checking some tutorials at Getting Ready for .NET 3.5 and LINQ – Exploring C# 3.0 – Part I  and over here.
We will be using a sample file called ‘Employees.xml’ for our samples. The mark up will be as follows:
<?xml version="1.0" encoding="utf-8" ?>
<Employees>
 <Employee>
    <EmpId>1</EmpId>
    <Name>Sam</Name>   
    <Sex>Male</Sex>
    <Phone Type="Home">423-555-0124</Phone>
    <Phone Type="Work">424-555-0545</Phone>
    <Address>
      <Street>7A Cox Street</Street>
      <City>Acampo</City>
      <State>CA</State>
      <Zip>95220</Zip>
      <Country>USA</Country>
    </Address>
 </Employee>
 <Employee>
    <EmpId>2</EmpId>
    <Name>Lucy</Name>
    <Sex>Female</Sex>
    <Phone Type="Home">143-555-0763</Phone>
    <Phone Type="Work">434-555-0567</Phone>
    <Address>
      <Street>Jess Bay</Street>
      <City>Alta</City>
      <State>CA</State>
      <Zip>95701</Zip>
      <Country>USA</Country>
    </Address>
 </Employee>
 <Employee>
    <EmpId>3</EmpId>
    <Name>Kate</Name>
    <Sex>Female</Sex>
    <Phone Type="Home">166-555-0231</Phone>
    <Phone Type="Work">233-555-0442</Phone>
    <Address>
      <Street>23 Boxen Street</Street>
      <City>Milford</City>
      <State>CA</State>
      <Zip>96121</Zip>
      <Country>USA</Country>
    </Address>
 </Employee>
 <Employee>
    <EmpId>4</EmpId>
    <Name>Chris</Name>
    <Sex>Male</Sex>
    <Phone Type="Home">564-555-0122</Phone>
    <Phone Type="Work">442-555-0154</Phone>
    <Address>
      <Street>124 Kutbay</Street>
      <City>Montara</City>
      <State>CA</State>
      <Zip>94037</Zip>
      <Country>USA</Country>
    </Address>
 </Employee>
</Employees>
 
The application is a console application targeting .NET 3.5 framework. I have used query expressions instead of Lambda expression in these samples. It is just a matter of preference and you are free to use any of these. Use the following namespaces while testing the samples: System; System.Collections.Generic; System.Linq; System.Text; System.Xml; System.Xml.Linq; System.IO;
9. Create an XML Document with Xml Declaration/Namespace/Comments using LINQ to XML
When you need to create an XML document containing XML declaration, XML Document Type (DTD), Processing instructions, Comments, Namespaces; you should go in for the XDocument class.
C#
XNamespace empNM = "urn:lst-emp:emp";
 
XDocument xDoc = new XDocument(
            new XDeclaration("1.0", "UTF-16", null),
            new XElement(empNM + "Employees",
                new XElement("Employee",
                    new XComment("Only 3 elements for demo purposes"),
                    new XElement("EmpId", "5"),
                    new XElement("Name", "Kimmy"),
                    new XElement("Sex", "Female")
                    )));
 
StringWriter sw = new StringWriter();
xDoc.Save(sw);
Console.WriteLine(sw);
VB.NET
        Dim empNM As XNamespace = "urn:lst-emp:emp"
 
        Dim xDoc As New XDocument(New XDeclaration("1.0", "UTF-16", Nothing), _
                    New XElement(empNM + "Employees", _
                    New XElement("Employee", _
                    New XComment("Only 3 elements for demo purposes"), _
                    New XElement("EmpId", "5"), _
                    New XElement("Name", "Kimmy"), _
                    New XElement("Sex", "Female"))))
 
        Dim sw As New StringWriter()
        xDoc.Save(sw)
        Console.WriteLine(sw)
LINQ
10. Save the XML Document to a XMLWriter or to the disk using LINQ to XML
Use the following code to save the XML to a XMLWriter or to your physical disk
C#
XNamespace empNM = "urn:lst-emp:emp";
 
XDocument xDoc = new XDocument(
            new XDeclaration("1.0", "UTF-16", null),
            new XElement(empNM + "Employees",
                new XElement("Employee",
                    new XComment("Only 3 elements for demo purposes"),
                    new XElement("EmpId", "5"),
                    new XElement("Name", "Kimmy"),
                    new XElement("Sex", "Female")
                    )));
 
StringWriter sw = new StringWriter();
XmlWriter xWrite = XmlWriter.Create(sw);
xDoc.Save(xWrite);
xWrite.Close();
 
// Save to Disk
xDoc.Save("C:\\Something.xml");
Console.WriteLine("Saved");
VB.NET
       Dim empNM As XNamespace = "urn:lst-emp:emp"
 
Dim xDoc As New XDocument(New XDeclaration("1.0", "UTF-16", Nothing),_
        New XElement(empNM + "Employees", _
        New XElement("Employee", _
        New XComment("Only 3 elements for demo purposes"), _
        New XElement("EmpId", "5"), _
        New XElement("Name", "Kimmy"), _
        New XElement("Sex", "Female"))))
 
        Dim sw As New StringWriter()
        Dim xWrite As XmlWriter = XmlWriter.Create(sw)
        xDoc.Save(xWrite)
        xWrite.Close()
 
        ' Save to Disk
        xDoc.Save("C:\Something.xml")
        Console.WriteLine("Saved")
11. Load an XML Document using XML Reader using LINQ to XML
Use the following code to load the XML Document into an XML Reader
C#
XmlReader xRead = XmlReader.Create(@"..\\..\\Employees.xml");
XElement xEle = XElement.Load(xRead);
Console.WriteLine(xEle);
xRead.Close();
VB.NET
Dim xRead As XmlReader = XmlReader.Create("..\\..\\Employees.xml")
Dim xEle As XElement = XElement.Load(xRead)
Console.WriteLine(xEle)
xRead.Close()
LINQ
12. Find Element at a Specific Position using LINQ to XML
Find the 2nd Employee Element
C#
// Using XElement
Console.WriteLine("Using XElement");
XElement xEle = XElement.Load("..\\..\\Employees.xml");
var emp = xEle.Descendants("Employee").ElementAt(1);
Console.WriteLine(emp);
 
Console.WriteLine("------------");
 
//// Using XDocument
Console.WriteLine("Using XDocument");
XDocument xDoc = XDocument.Load("..\\..\\Employees.xml");
var emp1 = xDoc.Descendants("Employee").ElementAt(2);
Console.WriteLine(emp);
VB.NET
' Using XElement
Console.WriteLine("Using XElement")
Dim xEle As XElement = XElement.Load("..\..\Employees.xml")
Dim emp = xEle.Descendants("Employee").ElementAt(1)
Console.WriteLine(emp)
 
Console.WriteLine("------------")
 
'// Using XDocument
Console.WriteLine("Using XDocument")
Dim xDoc As XDocument = XDocument.Load("..\..\Employees.xml")
Dim emp1 = xDoc.Descendants("Employee").ElementAt(2)
Console.WriteLine(emp)
LINQ
13. List the First 2 Elements using LINQ to XML
List the details of the first 2 Employees
C#
XElement xEle = XElement.Load("..\\..\\Employees.xml");
var emps = xEle.Descendants("Employee").Take(2);
foreach (var emp in emps)
    Console.WriteLine(emp);
VB.NET
Dim xEle As XElement = XElement.Load("..\..\Employees.xml")
Dim emps = xEle.Descendants("Employee").Take(2)
For Each emp In emps
      Console.WriteLine(emp)
Next emp
LINQ
14. List the 2nd and 3rd Element using LINQ to XML
List the 2nd and 3rd Employees
C#
XElement xEle = XElement.Load("..\\..\\Employees.xml");
var emps = xEle.Descendants("Employee").Skip(1).Take(2);
foreach (var emp in emps)
    Console.WriteLine(emp);
VB.NET
Dim xEle As XElement = XElement.Load("..\..\Employees.xml")
Dim emps = xEle.Descendants("Employee").Skip(1).Take(2)
For Each emp In emps
      Console.WriteLine(emp)
Next emp
LINQ
15. List the Last 2 Elements using LINQ To XML
We have been posting the entire elements as output in our previous examples. Let us say that you want to display only the Employee Name, use this query:
C#
XElement xEle = XElement.Load("..\\..\\Employees.xml");
var emps = xEle.Descendants("Employee").Reverse().Take(2);
foreach (var emp in emps)
    Console.WriteLine(emp.Element("EmpId") + "" + emp.Element("Name"));
VB.NET
Dim xEle As XElement = XElement.Load("..\..\Employees.xml")
Dim emps = xEle.Descendants("Employee").Reverse().Take(2)
For Each emp In emps
      Console.WriteLine(emp.Element("EmpId") + emp.Element("Name"))
Next emp
LINQ
To display only the values without the XML tags, use the ‘Value’ property
C#
XElement xEle = XElement.Load("..\\..\\Employees.xml");
var emps = xEle.Descendants("Employee").Reverse().Take(2);
foreach (var emp in emps)
    Console.WriteLine(emp.Element("EmpId").Value + ". " + emp.Element("Name").Value);
 
VB.NET
Dim xEle As XElement = XElement.Load("..\..\Employees.xml")
Dim emps = xEle.Descendants("Employee").Reverse().Take(2)
For Each emp In emps
      Console.WriteLine(emp.Element("EmpId").Value & ". " & emp.Element("Name").Value)
Next emp
LINQ
If you notice, the results are not ordered i.e. the Employee 4 is printed before 3. To order the results, one of the ways is to call Reverse() again while filtering as shown below. Note that I have not tested performance while using this query on a large document. If I find any performance issues, I will update this section:
C#
XElement xEle = XElement.Load("..\\..\\Employees.xml");
var emps = xEle.Descendants("Employee").Reverse().Take(2).Reverse();
foreach (var emp in emps)
    Console.WriteLine(emp.Element("EmpId").Value + ". " + emp.Element("Name").Value);
VB.NET
Dim xEle As XElement = XElement.Load("..\..\Employees.xml")
Dim emps = xEle.Descendants("Employee").Reverse().Take(2).Reverse()
For Each emp In emps
      Console.WriteLine(emp.Element("EmpId").Value & ". " & emp.Element("Name").Value)
Next emp
LINQ
16. Find the Element Count based on a condition using LINQ to XML
Count the number of Employees living in the state CA
C#
XElement xelement = XElement.Load("..\\..\\Employees.xml");
var stCnt = from address in xelement.Elements("Employee")
            where (string)address.Element("Address").Element("State") == "CA"
            select address;
Console.WriteLine("No of Employees living in CA State are {0}", stCnt.Count());
VB.NET
XElement xelement = XElement.Load("..\\..\\Employees.xml");
var stCnt = from address in xelement.Elements("Employee")
            where (string)address.Element("Address").Element("State") == "CA"
            select address;
Console.WriteLine("No of Employees living in CA State are {0}", stCnt.Count());
LINQ
Well those were some 'more' commonly used 'How Do I' operations while using LINQ to XML. In the Part 3 of this series, we will see how to manipulate XML content and persist the changes. The entire source code of the article in C# and VB.NET can be downloaded over here. I hope you liked the article and I thank you for viewing it.
Was this article worth reading? Share it with fellow developers too. Thanks!
Share on LinkedIn
Share on Google+
Further Reading - Articles You May Like!
Author
Suprotim Agarwal, MCSD, MCAD, MCDBA, MCSE, is the founder of DotNetCurry, DNC Magazine for Developers, SQLServerCurry and DevCurry. He has also authored a couple of books 51 Recipes using jQuery with ASP.NET Controls and a new one recently at The Absolutely Awesome jQuery CookBook.

Suprotim has received the prestigious Microsoft MVP award for nine times in a row now. In a professional capacity, he is the CEO of A2Z Knowledge Visuals Pvt Ltd, a digital group that represents premium web sites and digital publications comprising of Professional web, windows, mobile and cloud developers, technical managers, and architects.

Get in touch with him on Twitter @suprotimagarwal, LinkedIn or befriend him on Facebook



Page copy protected against web site content infringement 	by Copyscape




Feedback - Leave us some adulation, criticism and everything in between!
Comment posted by Rajasekaran on Wednesday, February 4, 2009 6:27 AM
Very good exploration
Comment posted by george on Sunday, March 22, 2009 6:18 AM
excellent
Comment posted by Peter on Wednesday, October 28, 2009 1:03 PM
There are 2 bugs here:  
#1 it should be emp1 not emp.
#2 it should be .ElementAt(1) not .ElementAt(2) -- which displayed the 3rd employee

12. Find Element at a Specific Position using LINQ to XML
Find the 2nd Employee Element

Dim emp1 = xDoc.Descendants("Employee").ElementAt(2)
Console.WriteLine(emp)