This tutorial demonstrates, and provides examples of, querying an XML document using an XElement. It demonstrates the use of XElement and LINQ extension methods (method syntax) and LINQ query expressions (expression syntax).

There are many ways to query (parse) XML, perhaps too many. Using an XDocument or XElement is preferable to the older technology of XMLdocument. (I believe XDocument was introduced in .NET 3.5.) XDocument uses LINQ to SQL, enabling query expression syntax (From.. Select..).

XPath is another approach. XPath is powerful, and is not specific to .NET or Microsoft, but the expression syntax requires a little effort to master.

The various approaches can actually be combined when parsing a single XML document. This gives us a lot of choices but can also be overwhelming for a beginner. Working with an XElement is both powerful and relatively straightforward, as I hope to show in this tutorial.

I've mentioned both XDocument and XElement. An XDocument includes the XML declaration, XML Document Type (DTD) and any processing instructions. XDocument also contains a single root XElement. You might obtain an XDocument and then use:

Dim xml As XElement = xmlDoc.Root

and the bulk of your work, querying, will be against this (simpler) object. You'll see this in the code.

You will hear the terms tag, node and element used interchangeably. Tag is more commonly used with HTML, and element is the term that the official XML documentation uses. People tend to use the term node when talking more formally about a document structure (rather than about specific document content). Unfortunately, it is too late to persuade people to use consistent terminology.

Note that we need to use .Value to obtain the text within the Element.

Read grouped element's content

Console.WriteLine("Titles and Authors:")
For Each book In books
Console.WriteLine("Title: {0}, Author: {1}", _
book.Element("title").Value, book.Element("author").Value)
Next

Note that it is a little tricky to always think of good, descriptive, titles for each piece of code. It will help you later (when searching this tutorial) if you consider that I start with simple examples and move to more complex examples.

Method syntax: Take(), OrderBy(), OrderByDescending()

The following code demonstrates using Enumerable methods (Take(), OrderBy()) to obtain information from the first two books.

You can choose to use expression or method syntax, and they can even be combined. Expression syntax is similar to SQL but notice that the word From occurs first.

Note also that, in the query expression, we don't always have to explicitly use .Value. Outside of a query expression we most often will need to use .Value.

Select by attribute value

Our sample file only has a single attribute, the id. If you wanted to find a specific id you could change the following to use:

Where CStr(bk.Attribute("id")) = "bk102"

I demonstrate a slightly more sophisticated example using the Like operator.

Console.WriteLine("Select by Attribute 'id' (#1#)")
Dim bookWith1 = From bk In books
Where CStr(bk.Attribute("id")) Like "bk#1#"
Select bk
For Each book As XElement In bookWith1
Console.WriteLine(book.Element("title").Value)
Next
'Microsoft .NET: The Programming Bible
'MSXML3: A Comprehensive Guide
'Visual Studio 7: A Comprehensive Guide

The hash-sign is a placeholder for a number, whereas a question mark would represent a character (a letter or number).

I'm sure there are many other ways to achieve this; this is the way that occurred to me, using Count(). (If you have an alternative I would be interested to see it, please include it in a response below.)

Get unique list of nested tag-values

List all the unique tags. This example demonstrates the use of the Let, Order By and Distinct clauses.