Querying an ASP.NET SiteMap using LINQ
A few days ago, Malcolm Sheridan wrote a cool article about Creating Dynamic ASP.NET SiteMap using LINQ. In this article, I will show you how to ‘query’ the ASP.NET SiteMap using LINQ. The intention of this article is to demonstrate the power and simplicity of querying an XML document like the ASP.NET SiteMap using LINQ. The SiteMap has a lot of similar elements like the <siteMapNodewhich would make it look difficult to query a structure like this, but LINQ makes the process look as simple as shown in this article.
The sample web.sitemap used in this article is shown below:
<?xml version="1.0" encoding="utf-8"?>
<siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0">
<siteMapNode title="My Favorites">
<siteMapNode title="Favorite Sites">
<siteMapNode title="ASP.NET Home" url="http://www.asp.net" />
<siteMapNode title="ASP.NET Articles" url="https://www.dotnetcurry.com"/>
<siteMapNode title="Windows Client" url="http://www.windowsclient.net" />
<siteMapNode title="Silverlight" url="http://silverlight.net" />
</siteMapNode>
<siteMapNode title="Favorite Blogs">
<siteMapNode title="ScottGu Blog" url="http://weblogs.asp.net/scottgu"/>
<siteMapNode title="Technology Blog" url="http://www.devcurry.com" />
<siteMapNode title="SQL Blog" url="http://www.sqlservercurry.com" />
<siteMapNode title="Food Lovers" url="http://foodatarian.com" />
</siteMapNode>
<siteMapNode title="Favorite Social Sites">
<siteMapNode title="Twitter" url="http://twitter.com/"/>
<siteMapNode title="FaceBook" url="http://www.facebook.com" />
<siteMapNode title="LinkedIn" url="http://www.linkedin.com" />
<siteMapNode title="Orkut" url="http://www.orkut.com" />
</siteMapNode>
</siteMapNode>
</siteMap>
I am using a BulletedList control (linkList) to display the results of the query. Observe that I have set the DisplayMode as ‘Hyperlink’ for the BulletedList control.
<asp:BulletedList ID="linkList" DisplayMode="HyperLink" runat="server">
</asp:BulletedList>
Let us get started.
List all Url’s in the SiteMap using LINQ
If you want to list down all the Url’s in the SiteMap, then here’s how to do so. We first retrieve a collection of attributes for the descendant elements and then retrieve the value of the ‘url’ attribute. The results are then bound to a Bulleted List.
C#
XElement xelement = XElement.Load(Server.MapPath("~/web.sitemap"));
var urlList = xelement.Descendants().Attributes()
.Where(x => x.Name == "url")
.Select(x => x.Value);
foreach (string s in urlList)
{
linkList.Items.Add(s);
}
VB.NET
Dim xelement As XElement = XElement.Load(Server.MapPath("~/web.sitemap"))
Dim urlList = xelement.Descendants().Attributes().Where(Function(x) x.Name = "url").Select(Function(x) x.Value)
For Each s As String In urlList
linkList.Items.Add(s)
Next s
Output:
List Url’s and Title in the SiteMap using LINQ
In order to list both the Url’s and Title in the SiteMap using LINQ, here’s another way to retrieve the value of desired attributes. We first select those nodes which contain the attribute ‘url’. We then select the value of the title and url attribute and bind the results to a Bulleted List
C#
XElement xelement1 = XElement.Load(Server.MapPath("~/web.sitemap"));
var urlDescList = xelement1.Descendants()
.Where(element => element.LastAttribute.Name.LocalName.Contains("url"))
.Select(nd => new
{
title = nd.Attribute("title")
.Value,
url = nd.Attribute("url")
.Value
});
foreach (var v in urlDescList)
{
ListItem li = new ListItem(v.title, v.url);
linkList.Items.Add(li);
}
VB.NET
Dim xelement1 As XElement = XElement.Load(Server.MapPath("~/web.sitemap"))
Dim urlDescList = xelement1.Descendants().Where(Function(element) element.LastAttribute.Name.LocalName.Contains("url")).Select(Function(nd) New With {Key .title = nd.Attribute("title").Value, Key .url = nd.Attribute("url").Value})
For Each v In urlDescList
Dim li As New ListItem(v.title, v.url)
linkList.Items.Add(li)
Next v
Output:
List Url’s and Title of a particular node of the SiteMap using LINQ
If you want to list down the Url’s and Titles of only the ‘Favorite Social Sites’ node, then here’s how to do so. We first select the node with ‘Favorite Social Sites’ and then use SelectMany() to flatten the sequence into once sequence. The last step is to retrieve the Url and Title from this sequence.
C#
XElement xelement2 = XElement.Load(Server.MapPath("~/web.sitemap"));
var urlDescList1 = xelement2.Descendants()
// Select node with 'Favorite Social Sites'
.Where(sel => (string)sel.Attribute("title") == "Favorite Social Sites")
.SelectMany(sel => sel.Elements())
.Select(nd => new
{
title = nd.Attribute("title").Value,
url = nd.Attribute("url").Value
});
foreach (var s in urlDescList1)
{
ListItem li = new ListItem(s.title, s.url);
linkList.Items.Add(li);
}
VB.NET
Dim xelement2 As XElement = XElement.Load(Server.MapPath("~/web.sitemap"))
' Select node with 'Favorite Social Sites'
Dim urlDescList1 = xelement2.Descendants().Where(Function(sel) CStr(sel.Attribute("title")) = "Favorite Social Sites").SelectMany(Function(sel) sel.Elements()).Select(Function(nd) New With {Key .title = nd.Attribute("title").Value, Key .url = nd.Attribute("url").Value})
For Each s In urlDescList1
Dim li As New ListItem(s.title, s.url)
linkList.Items.Add(li)
Next s
Output:
Count the number of nodes in each parent element of SiteMap using LINQ
In order to display the count of child nodes for each parent node of the SiteMap using LINQ, use this query:
C#
XElement xelement3 = XElement.Load(Server.MapPath("~/web.sitemap"));
var t = xelement3.Descendants()
.Where(x => x.LastAttribute.Name.LocalName != "url")
.Select(ele => new
{
Name = (string)ele.Attribute("title"),
Count = ele.Elements().Count()
});
VB.NET
Dim xelement3 As XElement = XElement.Load(Server.MapPath("~/web.sitemap"))
Dim t = xelement3.Descendants() _
.Where(Function(x) x.LastAttribute.Name.LocalName <> "url") _
.Select(Function(ele) New With {Key .Name = CStr(ele.Attribute("title")), _
Key .Count = ele.Elements().Count()})
Output:
So these were some examples of how to query an ASP.NET SiteMap using LINQ. Your SiteMap may differ from the one I have used for this sample, but I hope this article gives you an insight of how simple it is to query an XML document like the SiteMap using LINQ. If you would like to learn more about querying an XML document, I would suggest you to read my 3 Part ‘Some Common Operations using LINQ To XML’ series over here:
I hope you liked the article and I thank you for viewing it.
This article has been editorially reviewed by Suprotim Agarwal.
C# and .NET have been around for a very long time, but their constant growth means there’s always more to learn.
We at DotNetCurry are very excited to announce The Absolutely Awesome Book on C# and .NET. This is a 500 pages concise technical eBook available in PDF, ePub (iPad), and Mobi (Kindle).
Organized around concepts, this Book aims to provide a concise, yet solid foundation in C# and .NET, covering C# 6.0, C# 7.0 and .NET Core, with chapters on the latest .NET Core 3.0, .NET Standard and C# 8.0 (final release) too. Use these concepts to deepen your existing knowledge of C# and .NET, to have a solid grasp of the latest in C# and .NET OR to crack your next .NET Interview.
Click here to Explore the Table of Contents or Download Sample Chapters!
Was this article worth reading? Share it with fellow developers too. Thanks!
Suprotim Agarwal, MCSD, MCAD, MCDBA, MCSE, is the founder of
DotNetCurry,
DNC Magazine for Developers,
SQLServerCurry and
DevCurry. He has also authored a couple of books
51 Recipes using jQuery with ASP.NET Controls and
The Absolutely Awesome jQuery CookBook.
Suprotim has received the prestigious Microsoft MVP award for Sixteen consecutive years. In a professional capacity, he is the CEO of A2Z Knowledge Visuals Pvt Ltd, a digital group that offers Digital Marketing and Branding services to businesses, both in a start-up and enterprise environment.
Get in touch with him on Twitter @suprotimagarwal or at LinkedIn