Web Development

Access XML data using LINQ to XML

Tony Patton focuses on what he thinks is one of the more exciting aspects of the LINQ technology: working with XML. LINQ to XML allows you to create, read, and write XML-based data.

I have covered the basics about .NET Language-Integrated Query (LINQ) and provided information on working with a SQL Server backend via LINQ. This article focuses on what I think is one of the more exciting aspects of the LINQ technology: working with XML. LINQ to XML offers a cleaner approach to working with XML than the more cumbersome non-LINQ approaches.

The basics about LINQ to XML

LINQ to XML is a built-in LINQ data provider available in .NET 3.5. It is offered via the System.Xml.Linq namespace. LINQ to XML allows you to create, read, and write XML-based data. The XML data source may be a file, in-memory XML, or a remote resource accessed via protocols like HTTP.

The XDocument class in the System.Xml.Linq namespace includes various methods and properties that simplify working with XML data. The following list provides a sampling of these methods and properties:

  • Add: Allows you to add an element to the XML document.
  • AddFirst: Adds a new element to the top of the XML document.
  • Ancestors: Accesses the ancestors for an element.
  • Descendants: Accesses the descendant elements of a particular element.
  • Element: Accesses an individual element within the XML document.
  • FirstNode: Returns the first child node of an element.
  • IsAfter: Determines if the current node appears after a specified node in terms of document order.
  • IsBefore: Determines if the current node appears before a specified node in terms of document order.
  • LastNode: Returns the last child node of an element.
  • NextNode: Returns the next sibling node of the current node.
  • PreviousNode: Returns the previous sibling node of the current node.
  • RemoveNodes: Removes child nodes from a document or element.
  • Root: Gets the root element of the XML Tree for this document.
  • Save: Allows you to serialize the XDocument object to a file, TextWriter object, or XmlWriter object.
  • WriteTo: Allows you to write an XML document to an XmlWriter object.

These methods and properties are only the tip of the iceberg of working with LINQ to XML. The System.Xml.Linq namespace includes classes for every aspect of XML and many more, including XComment, XDeclaration, XElement, XName, XNamespace, XElement, and XObject. MSDN offers more information on the System.Xml.Linq namespace.

LINQ to XML is much simpler to use than other approaches such as using the XmlReader and XmlWriter classes within the System.Xml namespace. The best way to demonstrate ease-of-use is through an example.

In action

The XML in the following example defines an XML document with a root node called site. This root node contains one or more nodes called sites that include elements called name and url. The site element includes an attribute called technical.

<?xml version="1.0" encoding="utf-8" standalone="yes"?>

<sites>

<site technical="true">

<name>TechRepublic</name>

<url>www.techrepublic.com</url>

</site>

<site technical="true">

<name>News</name>

<url>www.news.com</url>

</site>

<site technical="true">

<name>CNET</name>

<url>www.cnet.com</url>

</site>

<site technical="false">

<name>GameSpot</name>

<url>www.gamespot.com</url>

</site>

</sites>

The data from the XML document is loaded, and the values stored in the name and url elements are displayed. The following C# code loads the XML from a local file into an XDocument object. The XDocument is used to select the items to display via its Descendants property in the from clause. I will basically query each of the site elements within the XML document. Finally, a foreach block is used to loop through every element loaded via the select statement and displayed via the Console object.

XDocument xmlDoc = XDocument.Load(@"c:sites.xml");

var q = from c in xmlDoc.Descendants("site")

select (string)c.Element("name") + " -- " +(string)c.Element("url");

foreach (string name in q) {

Console.WriteLine("Site: " + name);

}

The next example takes the concept further by filtering data via a where clause. The code snippet selects and displays only those site elements with a true value in its technical attribute. The where clause uses the Attribute property to check for the desired value.

XDocument xmlDoc = XDocument.Load(@"c:sites.xml");

var q = from c in xmlDoc.Descendants("site")

where c.Attribute("technical").Value == "true"

select (string)c.Element("name") + " ==>" + (string)c.Element("url");

foreach (string name in q) {

Console.WriteLine("Site: " + name);
}

LINQ allows you to define anonymous types on the fly, so let's take the example a bit further. This next code snippet defines an anonymous type on the fly with two properties: name and url. It is created with the new keyword used in the select clause, and the properties are defined within the body of the new statement denoted by curly braces. The new type is accessed in the foreach block with each property used to display values.

XDocument xmlDoc = XDocument.Load(@"c:sites.xml");

var q = from c in xmlDoc.Descendants("site")

where c.Attribute("technical").Value == "true"

select new {

name = c.Element("name").Value,

url = c.Element("url").Value

};

foreach (var obj in q) {

Console.WriteLine ("Site: " + obj.name + " -- " + obj.url);

}

The results of a LINQ query can be used as a data source for a user interface control or another object. The following code uses the results of the previous query to bind to a GridView object. The GridView control is contained on the following ASP.NET page:

<html xmlns="http://www.w3.org/1999/xhtml" >

<head runat="server">

<title>LINQ to XML</title>

</head>

<body>

<form id="frmLINQtoXML" runat="server">

<div>

<asp:GridView ID="gvSites" runat="server"></asp:GridView>

</div></form></body></html>

The following code populates the GridView control:

public partial class _Default : System.Web.UI.Page {

protected void Page_Load(object sender, EventArgs e) {

XDocument xmlDoc = XDocument.Load(@"c:sites.xml");

var q = from c in xmlDoc.Descendants("site")

where c.Attribute("technical").Value == "true"

select new {

name = c.Element("name").Value,

url = c.Element("url").Value

};

gvSites.DataSource = q;

gvSites.DataBind();
} } }

This simple approach to accessing XML has many possibilities, including easily pulling data from an RSS feed, a Word document via WordML, or any other data source and easily binding to a user interface control for presentation.

A better way

Many developers espouse the merits of using LINQ to SQL over regular ADO.NET to work with backend databases; however, there are also a lot of developers who seem happy with the LINQ alternative to working with XML. LINQ to XML is a much simpler and often intuitive approach to XML data, and it is more efficient than using the DOM API via the XmlDocument object. It also brings a database-type approach to XML with the select, where, and from clauses for choosing data.

Have you taken a peek at the new LINQ features available in .NET? If so, do you envision using it to work with XML? Share your thoughts and experience with the Visual Studio Developer community.

Tony Patton began his professional career as an application developer earning Java, VB, Lotus, and XML certifications to bolster his knowledge.

---------------------------------------------------------------------------------------

Get weekly development tips in your inbox TechRepublic's free Visual Studio Developer newsletter, delivered each Wednesday, contains useful tips and coding examples on topics such as Web services, ASP.NET, ADO.NET, and Visual Studio .NET. Automatically subscribe today!

About

Tony Patton has worn many hats over his 15+ years in the IT industry while witnessing many technologies come and go. He currently focuses on .NET and Web Development while trying to grasp the many facets of supporting such technologies in a productio...

13 comments
lnabin
lnabin

This is very easy and useful example. I used to similar thing in different way, after reading this article I realised how easily could be done.

Godlikesme
Godlikesme

I believe that your explanation and code are somewhat incorrect. In describing the makeup of the XML document you state the following: [quote]The XML in the following example defines an XML document with a root node called [u][b]site[/b][/u]. This root node contains one or more nodes called [u][b]sites[/b][/u] that include elements called name and url. The site element includes an attribute called technical.[/quote] In fact, the root node is actually called [u][b]sites[/b][u] and contains one or more nodes called [u][b]site[/b][/u]. Not being nit-picky but it makes a huge difference because then the LINQ query and just about anything else you attempt will fail.

lukaz
lukaz

Thank you for excellent examples! With using System.Linq in addition to already specified namespace at the top of the article it all works perfectly.

SelvaSabaratnam
SelvaSabaratnam

Had a lot of trouble completing my assignment. Linq-to-XML makes it all seem pretty easy. I appreciate your sharing your knowledge. Made me say "what a wonderful world" again..

chraigs
chraigs

I use LINQ a lot with my xml, today i came across an unusual situation which has had me scratching my head. How do you handle xml when the nodes do not contain the same fields. say i had an xml file of various objects where each object had different number of properties

manas_chetan
manas_chetan

I have two xmls which are to be accessed using single Linq query. (XML1) emp1 empname (XML2) emp2 empname Now in two xmls i want to insert info in products,customers,quality,personnel tags in xml1 and in products,customers in xml2 using general linq query. can u throw some light on this using c# code Thanks Manas

trinhtomsk
trinhtomsk

Thank you very much. It's very useful for me.

etruss
etruss

When I try to print this article, nothing happens. Other articles print OK.

Tony Hopkinson
Tony Hopkinson

Not being mad keen on datasets, I've been looking at wholly service oriented architectures, where database content is exposed as xml documents through a webservice model. That's nice until you want to composite on an adhoc(ish) basis. Linq gives you this facility in a very natural and extensible way. Cleverer than a tin of brains. Using it intead of SQl on the database, I can't see a lot of use for, and I'm not sanguine about how efficient the autogenerated SQL would be, especially if the DBMS wasn't SQL Server.

Justin James
Justin James

I like LINQ to XML a lot. I still ahve the heart of a purist when it comes to the DB access, but I think that giving XML developers better tools is nothing but good, especially when it shares a common syntax with other query methods, as LINQ does. J.Ja