Hooked on LINQ

Hooked on LINQ - Developers' Wiki
for .NET Language Integrated Query

Companion book for this site
LINQ to Objects Using C# 4.0:
Using and Extending LINQ to Objects and Parallel LINQ (PLINQ)
Quick Search

Advanced Search »

LINQ to XML - 5 Minute Overview

This Page is locked
Modified: 2008/04/24 20:09 by t_magennis - Categorized as: LINQ to XML, Samples
I want feedback on this article. Please leave your comments in the discussion page (click on the Discuss button on the top-right of this page)


LINQ to XML is a new way to construct, write and read XML data in the .NET language of the developers’ choice. This new API simplifies working with XML data without having to resort to using additional language syntax like XPath or XSLT. LINQ to XML is not a replacement for any of the current DOM’s or XML class libraries; LINQ to XML in many cases overlaps their functionality and aims to provide a superior developer experience, but existing code will continue to work. One aspect of LINQ to XML is that it supports writing Query Expressions and can be combined with any of the other LINQ technologies to create or use XML data as a source or destination format.

LINQ to XML has a simple model for building XML documents by hand. Whether it be XML sources from a stream or file, or XML created on-the-fly in code there are only a few important types to know and understand. The main ones used in everyday activities are XDocument, XElement and XAttribute. The constructor of XDocument and XElement can take any number of optional nested arguments (called functional construction. To illustrate the functional constructor syntax, we can build an XML document using syntax like this:

XElement xml = new XElement("contacts", new XElement("contact", new XAttribute("contactId", "2"), new XElement("firstName", "Barry"), new XElement("lastName", "Gottshall") ), new XElement("contact", new XAttribute("contactId", "3"), new XElement("firstName", "Armando"), new XElement("lastName", "Valdes") ) );

Console.WriteLine(xml);

Barry Gottshall Armando Valdes Generating an XML document by hand by cascading attributes in the constructor. Called functional construction

A Visual Studio enhancement allows you to copy straight XML onto your clipboard and Paste this into your C# code file in the form of an XDocument / XElement constructor, like that shown in Figure 23. If you are a Visual Basic user, it gets even easier; you can simply supply XML inline as an argument in the constructor. This XML is parsed into matching XElement and XAttribute types as shown in this example.

        Dim contacts As XElement = _
            <contacts>
                <contact contactId="2">
                    <firstName>Barry</firstName>
                    <lastName>Gottshall</lastName>
                </contact>
                <contact contactId="3">
                    <firstName>Armando</firstName>
                    <lastName>Valdes</lastName>
                </contact>
            </contacts>

        Console.WriteLine(contacts)
        Console.ReadLine()
VB inline XML declaration syntax.

To make our XML fully developed, we can use the XDocument type. It is only necessary to use XDocument when adding top-level document constructs like comments or processing instructions (XElement‘s suffice for the XML body construction). Its constructor can take any number of optional arguments, including the types XComment, XDeclaration and XProcessingInstruction types in addition to a top-level XElement and its nested nodes. For instance, to build a RSS 2.0 compatible document we can write:

Code:
XDocument doc = new XDocument(
    new XDeclaration("1.0", "utf-8", "yes"),
    new XComment("Sample RSS Feed"),
    new XElement("rss", 
        new XAttribute("version", "2.0"),
        new XElement ("channel",
            new XElement("title", "RSS Channel Title"),
            new XElement("description", "RSS Channel Description."),
            new XElement("link", "http://aspiring-technology.com"),
            new XElement("item",
                new XElement("title", "First article title"),
                new XElement("description", "First Article Description"),
                new XElement("pubDate", DateTime.Now.ToUniversalTime()),
                new XElement("guid", Guid.NewGuid())),
            new XElement("item",
                new XElement("title", "Second article title"),
                new XElement("description", "Second Article Description"),
                new XElement("pubDate", DateTime.Now.ToUniversalTime()),
                new XElement("guid", Guid.NewGuid()))
            )
        )
     );


doc.Save(@"c:\sample.xml");


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

<rss version="2.0">
  <channel>
    <title>RSS Channel Title</title>
    <description>RSS Channel Description.</description>
    <link>http://aspiring-technology.com</link>
    <item>
      <title>First article title</title>
      <description>First Article Description</description>
      <pubDate>2006-12-05T20:53:53.53125</pubDate>
      <guid>ff7bbf19-9155-4773-913c-767bcbf09904</guid>
    </item>
    <item>
      <title>Second article title</title>
      <description>Second Article Description</description>
      <pubDate>2006-12-05T20:53:53.5625</pubDate>
      <guid>8a3fd5e8-b99f-49fe-8a43-7fb62d80c18c</guid>
    </item>
  </channel>
</rss>
Manually generating an RSS 2.0 File. Showing how XDocument adds the top-level elements.

Building XML documents by hand is an in-frequent task. We are more likely to need to generate XML from a current data-source, or to transform existing XML into a new format. LINQ to XML can be combined with any of the other LINQ technologies to easily add XML support. An example of this is generating an XML document of a relational data source from within a LINQ to SQL query. The key is to include the Query Expression in an XElement’s nested constructor arguments that has a select projection building sub-node XElement’s. When LINQ to XML finds an IQueryable, or IEnumerable interface result type in any of the XElement (or XDocument’s) constructor arguments, it repeats that projection for each record returned.

Code:
XElement xml = new XElement("contacts",
                    from c in db.Contacts
                    orderby c.ContactId
                    select new XElement("contact",
                              new XAttribute("contactId", c.ContactId),
                              new XElement("firstName", c.FirstName),
                              new XElement("lastName", c.LastName))
                    );


Output:
<contacts>
  <contact contactId="2">
    <firstName>Barney</firstName>
    <lastName>Gottshall</lastName>
  </contact>
  <contact contactId="3">
    <firstName>Armando</firstName>
    <lastName>Valdes</lastName>
  </contact>
  <contact contactId="4">
    <firstName>Adam</firstName>
    <lastName>Gauwain</lastName>
  </contact>
  ...
</contacts>
When an IEnumerable or IQueryable result is found, the projection is repeated for each item in the sequence.

Loading XML from files or streams is just as easy. The XDocument and XElement types have a load and a parse method for creating or creating from an XML file source or stream.

Code:
HookedOnLINQ db = 
new HookedOnLINQ("Data Source=(local);Initial Catalog=HookedOnLINQ");


XElement xml = new XElement("contacts",
                    from c in db.Contacts
                    orderby c.ContactId
                    select new XElement("contact",
                              new XAttribute("contactId", c.ContactId),
                              new XElement("firstName", c.FirstName),
                              new XElement("lastName", c.LastName))
                    );


// Saving to a file, you can also save to streams
xml.Save(@"C:\contacts.xml");


// Loading from a file, you can also load from a stream
XDocument loaded = XDocument.Load(@"C:\contacts.xml");
Saving and loading XML files from a file or stream is easy.

Once these files are loaded into the LINQ to XML API, you can write queries over that tree. The query syntax is easier than XPath or XQuery for developers who do not use XPath or XQuery on a daily basis.

Code:
// Loading from a file, you can also load from a stream
XDocument loaded = XDocument.Load(@"C:\contacts.xml");


// Query the data and write out a subset of contacts
var q = from c in loaded.Descendants("contact")
        where (int)c.Attribute("contactId") < 4
        select (string)c.Element("firstName") + “ “ +
 		   (string)c.Element("lastName");


foreach (string name in q)
    Console.WriteLine("Customer name = {0}", name);


Output:
Customer name = Barney Gottshall
Customer name = Armando Valdes
Query over XML document. Notice the casting and access methods (.Attribute and .Element)

In the previous example you will notice that all access to elements was a cast to the correct type, and also the requirement of .Attribute and .Element methods. At the time of writing, Microsoft was experimenting with how to achieve a strongly-typed developer experience when working with XML and released an alpha of LINQ to XSD. LINQ to XSD allows you to code against a strongly-typed object model and relieves you of having to handle typing and call specific access methods to retrieve elements and attributes. This simplifies the syntax of query expressions enormously, and allows Visual Studio to provide a rich developer experience with Intellisense and compile-time checking. In the previous example, we can rewrite this as long as the XML has a schema in the following way:

Code:
var xmlSource = contacts.Load(@"../../Contacts.xml");


var q = from c in xmlSource.contact
        where c.contactId < 4
        select c.firstName + " " + c.lastName;


foreach(string name in q)
    Console.WriteLine("Customer name = {0}", name);


Output:
Customer name = Barney Gottshall
Customer name = Armando Valdes


LINQ to XML - 5 Minute Overview is Copyright © Troy Magennis.

If you would like to comment on this page, click on the Discuss button located on the top-right of each page. Feel free to edit any mistakes or omissions you find. If you have an objection or find in-appropriate content then contact the administrator. This website is not affiliated with Microsoft®, all content and opinions are those of the specific author and some advice, solutions and article may contain unintentional errors - please use care. Other websites by this author: Focused Objective, Geek Speak Decoded.