Working with XML using Microsoft’s .NET Framework in version 2.0 and below is a cumbersome task. The API available follows the W3C DOM model and is document-centric. Everything begins with the document; you can’t create elements without having a document, even a fragment of XML, is a document.
In the latest release of the .NET Framework, however, this has changed. XML is now element-centric. With features like object initialization and anonymous types, it’s very easy to create XML. Add to this the features of LINQ and we now have a very easy to use and powerful tool for XML.
In this article I will explore some of the features available in .NET Framework release 3.5 related to XML and LINQ. This is, of course, not an extensive discussion of either subject, merely a familiarization and stepping stone for more learning and exploration.
The LINQ Part
When discussing LINQ to XML, or LINQ to whatever, the first thing that needs to be discussed is, of course LINQ.
LINQ
Language-Integrated query, or LINQ, is an extension to the .NET Framework in version 3.5 that makes queries and set operations first class citizens of .NET languages such as C#. It has been further defined as, “A set of general purpose standard query operators that allow traversal, filter, and projection operations to be expressed in a direct yet declarative way in any .NET language.”
Getting started
This is an example of a very basic LINQ query
string[] names = new string[] { "John", "Paul", "George", "Ringo" };
var name = names.Select(s => s);
Two things noticeable here is the var keyword and the strange-looking operator =>.
Var keyword
var is new datatype that has be introduced in 3.5. Although it looks similar to the var datatype in VB or JavaScript, it isn’t quite the same. In VB and JavaScript var represents a variant datatype, one that can be used to represent just about anything. In LINQ, however, var is more of a placeholder; the actual datatype is set at compile time and is inferred by the context it used in.
In the above example, name is a resolved to System.Linq.Enumerable.SelectIterator<string,bool>
var name = "Hello, World";
In this example though, name is resolved to a string.
This ambiguity is useful when you are unsure of what exactly will be returned from a query, and the fact that it is not necessary to cast the variable to another type before using it, is very convenient.
Lambda Expressions
Lambda expressions were first introduced in 1936 by mathematician Alonzo Church as a short hand for expressing algorithms. In .NET 3.5 they are a convenient way for developers to define functions that can be passed as arguments, and are an evolution of anonymous methods introduced in .NET 2.0.
The => operator is used to separate input variables, on the left, and the body of the expression on the right.
string[] names = new string[] { "John", "Paul", "George", "Ringo" };
var name = names.Select(s => s.StartsWith("P"));
In this example, each string in the names array is represented by the variable s. It’s not necessary to declare a datatype because it is inferred from the type of the collection, names in this case.
These two statements would be somewhat analogous
var name = names.Select(s => s);
foreach(string s in names) { }
The body of the expression, s.StartsWith("P"), just uses the string method to return a Boolean value. Select is an extension method (more on that shortly) for that takes as its parameter a Func object.
Func and Action
Func and Action are two new methods available in .NET 3.5, and are used to represent delegates.
This is used to represent a delegate that returns a value, TResult.
On the other hand, this is used to represent a delegate does not return a value.
The example we have been using can be rewritten as below
Func<string, bool> pOnly = delegate(string s) { return s.StartsWith("P"); };
string[] names = new string[] { "John", "Paul", "George", "Ringo" };
var name = names.Select(pOnly);
Sequences
Running the demo code from this article you will notice the in all of the examples above do not return a single value. Rather the return a collection of Boolean values indicating whether each element in the input collection matched the specified expression. This collection is referred to as a sequence in LINQ.
<formulas /></formulas />

If we wanted the single value the matched the expression, we would use the Single extension method.
string name = names.Single(pOnly);
Notice here that the name variable is typed as a string. Although we could still use var, we know that the return value is, or should be, a string.
Extension methods
Extension methods are a feature of .NET 3.5 that allows developers to add functionality to existing classes without modifying the code for the original class. A useful scenario when you want to provide additional functionality and don’t have access to the code base, such as when using third-party libraries.
Extension methods are static methods on static classes. The first parameter of these methods is typed as the datatype for which it is extending, and uses the this modifier. Notice that this is being used as a modifier, not as a reference to the current object.
public static class StringExtensions
{
public static int ToInt(this string number)
{
return Int32.Parse(number);
}
public static string DoubleToDollars(this double number)
{
return string.Format("{0:c}", number);
}
public static string IntToDollars(this int number)
{
return string.Format("{0:c}", number);
}
}
When this class in compiled, .NET applies the System.Runtime.CompilerServices.Extension to it, and when it is in scope, Intellisence can read this information and determine which methods apply based on the datatype.


As we can see here, in the first example Intellisence knows that on the ToInt method applies to strings, and only DoubleToDollars applies to doubles.
Query Expression and Methods
There are two ways to execute LINQ queries, what is known as query expression and dot-notation. The former resembles a SQL query, except that the select clause is last.
string[] camps = new string[]{"CodeCamp2007","CodeCamp2008","CodeCamp2009"};
var currentCamp = from camp in camps
where camp.EndsWith(DateTime.Now.Year.ToString())
select camp;
string currentCamp = camps.Single(c => c.EndsWith(DateTime.Now.Year.ToString()));
These two statements produce the same results because the query expression format is converted to methods at compile time. There are several ways to produce results with methods. Each of the below will produce the same results.
string currentCamp2 = camps.Where(c => c.EndsWith(DateTime.Now.Year.ToString())).Single();
string currentCamp3 = camps.Single(c => c.EndsWith(DateTime.Now.Year.ToString()));
string currentCamp4 = camps.Select(c => c).Where(c => c.EndsWith(DateTime.Now.Year.ToString())).Single();
The XML Part
Now that we have an understanding of LINQ, it’s time to move on the XML part.
For this article we will be using this XML file
<?xml version="1.0" encoding="utf-8" ?>
<employees>
<employee id="1" salaried="no">
<name>Gustavo Achong</name>
<hire_date>7/31/1996</hire_date>
</employee>
<employee id="3" salaried="yes">
<name>Kim Abercrombie</name>
<hire_date>12/12/1997</hire_date>
</employee>
<employee id="8" salaried="no">
<name>Carla Adams</name>
<hire_date>2/6/1998</hire_date>
</employee>
<employee id="9" salaried="yes">
<name>Jay Adams</name>
<hire_date>2/6/1998</hire_date>
</employee>
</employees>
The Old Way
In previous versions of the .NET Framework, XML was document-centric, in other words, to create any structure you first had to start with an XMLDocument.
Collapse
public class OldWay
{
private static XmlDocument m_doc = new XmlDocument();
public static void CreateEmployees()
{
XmlElement root = m_doc.CreateElement("employees");
root.AppendChild(AddEmployee(1, "Gustavo Achong", DateTime.Parse("7/31/1996"), false));
root.AppendChild(AddEmployee(3, "Kim Abercrombie", DateTime.Parse("12/12/1997"), true));
root.AppendChild(AddEmployee(8, "Carla Adams", DateTime.Parse("2/6/1998"), false));
root.AppendChild(AddEmployee(9, "Jay Adams", DateTime.Parse("2/6/1998"), false));
m_doc.AppendChild(root);
Console.WriteLine(m_doc.OuterXml);
}
private static XmlElement AddEmployee(int ID, string name, DateTime hireDate, bool isSalaried)
{
XmlElement employee = m_doc.CreateElement("employee");
XmlElement nameElement = m_doc.CreateElement("name");
nameElement.InnerText = name;
XmlElement hireDateElement = m_doc.CreateElement("hire_date");
hireDateElement.InnerText = hireDate.ToShortDateString();
employee.SetAttribute("id", ID.ToString());
employee.SetAttribute("salaried", isSalaried.ToString());
employee.AppendChild(nameElement);
employee.AppendChild(hireDateElement);
return employee;
}
}
Smart developers would create helper methods to ease the pain, but it was still a verbose, cumbersome process. An XMLElement can’t be created on its own, it must be created from an XMLDocument.
XmlElement employee = m_doc.CreateElement("employee");
Trying to do this generate a compiler error.
XmlElement employee = new XmlElement();
Looking at the above example, it is also difficult to get an idea about the scheme for this document.
The New Way
Using the classes from the System.Xml.Linq namespace, and the features available in .NET 3.5, constructing an XML document is very easy and very readable.
Collapse
public static void CreateEmployees()
{
XDocument doc = new XDocument(
new XDeclaration("1.0", "utf-8", "yes"),
new XComment("A sample xml file"),
new XElement("employees",
new XElement("employee",
new XAttribute("id", 1),
new XAttribute("salaried", "false"),
new XElement("name", "Gustavo Achong"),
new XElement("hire_date", "7/31/1996")),
new XElement("employee",
new XAttribute("id", 3),
new XAttribute("salaried", "true"),
new XElement("name", "Kim Abercrombie"),
new XElement("hire_date", "12/12/1997")),
new XElement("employee",
new XAttribute("id", 8),
new XAttribute("salaried", "false"),
new XElement("name", "Carla Adams"),
new XElement("hire_date", "2/6/1998")),
new XElement("employee",
new XAttribute("id", 9),
new XAttribute("salaried", "false"),
new XElement("name", "Jay Adams"),
new XElement("hire_date", "2/6/1998"))
)
);
}
Constructing a document in this way is possible because of the functional construction feature in LINQ to XML. Functional construction is simply a means of create an entire document tree in a single statement.
public XElement(XName name, Object[] content)
As we can see from one of the constructors for XElement, it takes an array of objects. In the example above, the employees element is constructed from four XElements, one for each employee, which in turn is constructed from XAttributes and other XElements.
In the above example we could have replaced XDocument with XElement if we removed the XDeclaration and XComment objects. This is because the constructor XDocument used takes a XDeclaration instance, rather than the XName that the XElement constructor takes.
public XDocument(XDeclaration declaration,Object[] content)
Another thing to note when running the demo is how both documents are printed to the console window.

As we can see the old method just streams the contents of the document to the console. The method does that also, however, it is nicely formatted with no extra effort.
Namespace support
Namespaces are, of course, supported through the XNamespace class
XNamespace ns = "
http://mycompany.com/">http:
XElement doc =
new XElement(
new XElement(ns +
"employees",
new XElement(
"employee",
One this to note is that if one element uses a namespace, they all must use one. In the case above we can see that an empty xmlns attribute will be added to the employee element
<employees xmlns="http://mycompany.com">
<employee id="1" salaried="false" xmlns="">
Explicit conversion
One of the many nice thing with the new XML support is it support for explicit conversion of values.
Previously, all xml values were treated as strings and had to be converted as necessary.
idElement.InnerText = "42";
int id = Convert.ToInt32(idElement.Value);
With the new API this is much more intuitive
XElement element1 = new XElement("number", 42);
XElement element2 = new XElement("number", "42");
int num1 = (int)element1;
int num2 = (int)element2;
Traversing an XML tree
Traversing an XML tree is still very easy
foreach(var node in doc.Nodes())
We can use the nodes in collections of the document, or root element. Note here however that this will traverse the entire tree, including all children, not just the sibling nodes.
foreach(var node in doc.Nodes().OfType<XComment>())
This method can be used to traverse specific node node types, comments in this case. Or we can get to specific child nodes this way.
foreach(var node in doc.Elements("employees").Elements("employee").Elements("name"))
This is an improvement over nested iterations or obtaining an XMLNodeList with an XPath query.
XPath
XPath support has been built into the API through the use of extension methods such as:
- Descendents
- Ancestors
- DescendentsAndSelf
- AncestorsAndSelf
- ElementsBeforeSelf
- ElementsAfterSelf
This is not an extensive list, so check the documentation for all the others available.
Transforming XML
Transforming and XML document or element is still possible using the methods I’m sure we are all familiar with
XslTransform xslt = new XslTransform();
xslt.Load(stylesheet);
XPathDocument doc = new XPathDocument(filename);
XmlTextWriter writer = new XmlTextWriter(Console.Out);
xslt.Transform(doc, null, writer, null);
writer.Close();
However, with the new API we can make use of function construction and LINQ queries to transform a document
XElement element = new XElement("salaried_employees", from e in doc.Descendants("employee")
where e.Attribute("salaried").Value == "true"
select new XElement("employee",
new XElement(e.Element("name")) ) );
Conclusion
XML is fantastic construct that has been deeply ingrained into just about everything. Having the ability to easily construct, query, transform and manipulate XML documents is an invaluable service that will improve the speed of which applications can be built and the quality of those applications.
This article is not an exhaustive investigation of LINQ to XML; there have been many other articles, snippets and blogs written on the subject. It mainly just a taste and familiarization of what is possible using .NET 3.5.