Developer

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

Editor's Picks