Querying an ASP.NET SiteMap using LINQ

Posted by: Suprotim Agarwal , on 3/10/2009, in Category LINQ
Views: 78383
Abstract: 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.
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:
URL List 
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:
Url Desc List 
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:
Url DescList 
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:
UrlCount
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.
If you liked the article,  Subscribe to the RSS Feed or Subscribe Via Email  
 

This article has been editorially reviewed by Suprotim Agarwal.

Absolutely Awesome Book on C# and .NET

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!

What Others Are Reading!
Was this article worth reading? Share it with fellow developers too. Thanks!
Share on LinkedIn
Share on Google+

Author
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



Page copy protected against web site content infringement 	by Copyscape




Feedback - Leave us some adulation, criticism and everything in between!
Comment posted by Josh M on Tuesday, April 21, 2009 8:06 AM
Neat + Simple + Brilliant..!
Comment posted by Ankit on Thursday, April 23, 2009 12:48 AM
Thanks a lot. this is perfect
ankit
www.tops-int.com
Comment posted by Hims on Thursday, May 14, 2009 5:27 PM
Really superb post!
Great work.. thanks

<a href="http://www.freelance-seoindia.blogspot.com/">Freelance seo</a>
Comment posted by Anon on Wednesday, December 2, 2009 10:49 PM
Thank you so much for this.
Comment posted by Chefdog on Friday, November 8, 2013 8:24 AM
You could also, just to something like this: For example, query for a custom attribute called ShowInNavigation:

SiteMapNodeCollection coll = SiteMap.RootNode.ChildNodes;
                    IEnumerable<SiteMapNode> nodes = coll.Cast<SiteMapNode>();                    
                    var query = from node in nodes where Boolean.Parse(node["ShowInNavigation"]) == true select node;