Skip to main content

Microsoft Silverlight

MicrosoftWritten by:
Microsoft
Microsoft

LINQ TO XML

0 0

Summary

Describes hows how to use LINQ to filter, group, sort, transform, and project an RSS feed.

You can parse XML data in Silverlight by using either Language-Integrated Query (LINQ) to XML or the XmlReader class. One common XML scenario is parsing and transforming RSS feeds and displaying the content on a site. Because RSS is an XML format, LINQ to XML can be used to easily query and transform the RSS feed.

RSS feeds typically contain news content, but they can contain anything that can be organized into discrete items. In its simplest form, an RSS feed consists of a channel, which has a title, link, and description. An RSS feed can also contain one or more item elements, each of which has a title, link, description, and possibly other elements.

This QuickStart shows how to parse an RSS feed of programming books. Specifically, this QuickStart shows how to load the RSS feed, filter items by specified element, group items, sort items, transform the shape of the XML tree, and control the projection type.

This QuickStart contains the following sections:

For a complete description of LINQ to XML, see Processing XML Data with LINQ to XML in Silverlight in the Silverlight documentation on MSDN.


Loading an RSS File

In Silverlight, you can load XML files in the following ways:

The following example shows how to load and display the RSS file from the application's XAP package.

C#

// Load the RSS file into XElement and display the content of the XML tree on the page. // XmlXapResolver is used to load the file from the application's XAP package. XElement rss = XElement.Load("rss.xml"); OutputTextBoxLoadRss.Text = rss.ToString();

Visual Basic

' Load the RSS file into XElement and display the content of the XML tree on the page. ' XmlXapResolver is used to load the file from the application's XAP package. Dim rss As XElement = XElement.Load("rss.xml") OutputTextBoxLoadRss.Text = rss.ToString()

The following shows the content of the RSS file.

<rss version="2.0"> <channel> <title>Programming Books</title> <link>http://www.books.microsoft.com</link> <description>Download programming books</description> <pubDate>Thu, 27 Apr 2008 13:40:10 +0000</pubDate> <language>en</language> <item> <title> C# programming for beginners </title> <link>http://www.books.microsoft.com/beginners-cs/</link> <pubDate>Thu, 17 Apr 2008 13:40:10 +0000</pubDate> <category>C Sharp</category> <description> This is C# for beginners. </description> </item> <item> <title> VB programming for beginners </title> <link>http://www.books.microsoft.com/beginners-vb/</link> <pubDate>Thu, 15 Apr 2006 13:40:10 +0000</pubDate> <category>Visual Basic</category> <description> This is VB for beginners. </description> </item> <item> <title> C# in Depth </title> <link>http://www.books.microsoft.com/advanced-cs/</link> <pubDate>Thu, 13 Dec 2007 13:40:10 +0000</pubDate> <category>C Sharp</category> <description> This is advanced C# programming book. </description> </item> <item> <title> VB in Depth </title> <link>http://www.books.microsoft.com/advanced-vb/</link> <pubDate>Thu, 17 Oct 2008 13:40:10 +0000</pubDate> <category>Visual Basic</category> <description> This is advanced VB programming book. </description> </item> </channel> </rss>

Filtering an RSS XML Tree by Specific Elements

Often you want to work with a subset of XML data instead of the whole XML tree. In LINQ to XML, you can combine querying with functional construction to generate a new XML document that has a different shape from the original document. You can filter an XML document by specific elements to extract the data of interest.

The following example creates a query that finds item elements that have category child elements with a value of "C Sharp". The query returns an IEnumerable of XElement. The result of the query is passed as a second parameter to the constructor of the XElement. Finally, the code outputs the content of the newly created XElement object to the page.

C#

XElement filterCategory = new XElement("FilteringByCategory", from category in rss.Element("channel").Elements("item") where (string)category.Element("category") == "C Sharp" select new XElement("item", category.Elements() ) ); OutputTextBoxFilter.Text = filterCategory.ToString();

Visual Basic

Dim filterCategory = <FilteringByCategory> <%= From category In rss.<channel>.<item> _ Where category.<category>.Value.Contains("C Sharp") _ Select _ <item> <%= category.Elements %> </item> _ %></FilteringByCategory> OutputTextBoxFilter.Text = filterCategory.ToString()

The following shows the query output of filtering by the "C Sharp" category.

<FilteringByCategory> <item> <title> C# programming for beginners </title> <link>http://www.books.microsoft.com/beginners-cs/</link> <pubDate>Thu, 17 Apr 2008 13:40:10 +0000</pubDate> <category>C Sharp</category> <description> This is C# for beginners. </description> </item> <item> <title> C# in Depth </title> <link>http://www.books.microsoft.com/advanced-cs/</link> <pubDate>Thu, 13 Dec 2007 13:40:10 +0000</pubDate> <category>C Sharp</category> <description> This is advanced C# programming book. </description> </item> </FilteringByCategory>

Grouping an RSS XML Tree by Category

In many reports, you need to organize data into groups to make it easier to read and to analyze.

The following example shows how to group data, and then generate XML based on the grouping. The example creates a query that groups item elements by category. The query returns an IEnumerable of XElement. The result of the query is passed as a second parameter to the constructor of the XElement. Finally, the code outputs the content of the newly created XElement object to the page.

C#

XElement groupCategory = new XElement("GroupingByCategory", from item in rss.Element("channel").Elements("item") group item by (string)item.Element("category") into groupedData select new XElement("group", new XAttribute("Name", groupedData.Key), from g in groupedData select new XElement("item", g.Elements()) ) ); OutputTextBoxGroup.Text = groupCategory.ToString();

Visual Basic

Dim groupCategory = <GroupingByCategory> <%= From item In rss.<channel>.<item> _ Group By item = item.<category>.Value _ Into groupedData = Group _ Select _ <group Name=<%= item %>> <%= From g In groupedData _ Select _ <item> <%= g.Elements %> </item> %> </group> %> </GroupingByCategory> OutputTextBoxGroup.Text = groupCategory.ToString()

The following shows the query output of grouping by category.

<GroupingByCategory> <group Name="C Sharp"> <item> <title> C# programming for beginners </title> <link>http://www.books.microsoft.com/beginners-cs/</link> <pubDate>Thu, 17 Apr 2008 13:40:10 +0000</pubDate> <category>C Sharp</category> <description> This is C# for beginners. </description> </item> <item> <title> C# in Depth </title> <link>http://www.books.microsoft.com/advanced-cs/</link> <pubDate>Thu, 13 Dec 2007 13:40:10 +0000</pubDate> <category>C Sharp</category> <description> This is advanced C# programming book. </description> </item> </group> <group Name="Visual Basic"> <item> <title> VB programming for beginners </title> <link>http://www.books.microsoft.com/beginners-vb/</link> <pubDate>Thu, 15 Apr 2006 13:40:10 +0000</pubDate> <category>Visual Basic</category> <description> This is VB for beginners. </description> </item> <item> <title> VB in Depth </title> <link>http://www.books.microsoft.com/advanced-vb/</link> <pubDate>Thu, 17 Oct 2008 13:40:10 +0000</pubDate> <category>Visual Basic</category> <description> This is advanced VB programming book. </description> </item> </group> </GroupingByCategory>

Sorting an RSS XML Tree by Title

Sometimes you need to extract certain elements from an XML tree and display them in sorted order.

The following example shows how to write a query that sorts its results. The example creates a query that sorts item elements by title. The query returns an IEnumerable of String.

C#

IEnumerable<String> sortedTitles = from item in rss.Elements("channel").Elements("item") let title = (String)item.Element("title") orderby title select title; StringBuilder sb = new StringBuilder(); sb.AppendLine("Sorting by Title:"); foreach (String bookTitle in sortedTitles) sb.AppendLine(bookTitle.ToString()); OutputTextBoxSort.Text = sb.ToString();

Visual Basic

Dim sortedTitles As IEnumerable(Of String) = _ From item In rss.<channel>.<item> _ Let title = Convert.ToString(item.<title>.Value) _ Order By (title) _ Select title Dim sb As New StringBuilder sb.AppendLine("Sorting by Title:") Dim bookTitle As String For Each bookTitle In sortedTitles sb.AppendLine(bookTitle.ToString()) Next bookTitle OutputTextBoxSort.Text = sb.ToString()

The following shows the query output of sorting by title.

Sorting by Title: C# in Depth C# programming for beginners VB in Depth VB programming for beginners

Transforming the Shape of an RSS XML Tree

The shape of an XML document refers to its element names, attribute names, and the characteristics of its hierarchy. Sometimes you have to change the shape of an XML document. For example, you might have to send an existing XML document to another system that requires different element and attribute names.

The following example changes the shape of an XML file by using embedded query expressions. The source XML document contains a channel element under the rss root element. The channel element has a title, link, description, and item elements, each of which has a title, link, description, and other elements. The transformed XML tree contains book elements under the TransformingShape element that contains category, title, and pubDate child elements.

C#

XElement transformShape = new XElement("TransformingShape", from item in rss.Elements("channel").Elements("item") select new XElement("book", item.Elements("category"), item.Elements("title"), item.Elements("pubDate")) ); OutputTextBoxTransform.Text = transformShape.ToString();

Visual Basic

Dim transformShape = <TransformingShape> <%= From item In rss.<channel>.<item> _ Select <book> <%= item.<category> %> <%= item.<title> %> <%= item.<pubDate> %> </book> %> </TransformingShape> OutputTextBoxTransform.Text = transformShape.ToString()

The following shows the query output of transforming the shape.

<TransformingShape> <book> <category>C Sharp</category> <title> C# programming for beginners </title> <pubDate>Thu, 17 Apr 2008 13:40:10 +0000</pubDate> </book> <book> <category>Visual Basic</category> <title> VB programming for beginners </title> <pubDate>Thu, 15 Apr 2006 13:40:10 +0000</pubDate> </book> <book> <category>C Sharp</category> <title> C# in Depth </title> <pubDate>Thu, 13 Dec 2007 13:40:10 +0000</pubDate> </book> <book> <category>Visual Basic</category> <title> VB in Depth </title> <pubDate>Thu, 17 Oct 2008 13:40:10 +0000</pubDate> </book> </TransformingShape>

Controlling the Type of a Projection

Projection is the process of taking one set of data, filtering it, changing its shape, and even changing its type. Most query expressions perform projections. Most of the query expressions shown in this topic evaluate to IEnumerable of XElement. However, you can control the type of the projection to create collections of other types.

The following example defines a new type, Book. The query expression then instantiates new Book objects in the Select clause. This causes the type of the query expression to be IEnumerable of Book.

C#

public partial class Page : UserControl { public class Book { private string category; private string title; public Book(string category, string title) { this.category = category; this.title = title; } public override string ToString() { return String.Format("Category: {0} " + "Title:{1}", this.category, this.title); } } void ControllingProjectionType(XElement rss) { IEnumerable<Book> bookList = from item in rss.Elements("channel").Elements("item") select new Book( (string)item.Element("category"), (string)item.Element("title") ); StringBuilder sb = new StringBuilder(); sb.AppendLine("Controlling Projection Type:"); foreach (Book book in bookList) sb.AppendLine(book.ToString()); OutputTextBoxControlType.Text = sb.ToString(); } public Page() { InitializeComponent(); // Load the rss file. XElement rss = XElement.Load("rss.xml"); ControllingProjectionType(rss); } }

Visual Basic

Partial Public Class Page Inherits UserControl Public Class Book Private category As String Private title As String Public Sub New(ByVal category As String, _ ByVal title As String) Me.category = category Me.title = title End Sub Public Overrides Function ToString() As String Return String.Format("Category: {0} " & _ "Title:{1}", Me.category, Me.title) End Function End Class Sub ControllingProjectionType(ByVal rss As XElement) Dim bookList As IEnumerable(Of Book) = _ From item In rss.<channel>.<item> _ Select New Book( _ item.<category>.Value, _ item.<title>.Value) Dim sb As New StringBuilder() sb.AppendLine("ControllingType:") Dim book As Book For Each book In bookList sb.AppendLine(book.ToString()) Next book OutputTextBoxControlType.Text = sb.ToString() End Sub 'ControlProjectionType Public Sub New() InitializeComponent() Dim rss As XElement = XElement.Load("rss.xml") ControllingProjectionType(rss) End Sub End Class

The following shows the output of the projection to a Book type.

Controlling Projection Type: Category: C Sharp Title: C# programming for beginners Category: Visual Basic Title: VB programming for beginners Category: C Sharp Title: C# in Depth Category: Visual Basic Title: VB in Depth

See Also


Send Feedback

Leave a Comment Comments (0) RSS Feed

  • 1

You must be logged in to leave a comment. Click here to log in.

Quickstarts

Microsoft Communities