Querying an ASP.NET SiteMap using LINQ

Posted by: Suprotim Agarwal , on 3/10/2009, in Category LINQ
Views: 64977
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="http://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  
 
Give a +1 to this article if you think it was well written. Thanks!
Recommended Articles
Suprotim Agarwal, ASP.NET Architecture MVP, MCSD, MCAD, MCDBA, MCSE, is the CEO of A2Z Knowledge Visuals Pvt. He primarily works as an Architect Consultant and provides consultancy on how to design and develop .NET centric database solutions.

Suprotim is the founder and primary contributor to DotNetCurry, DNC .NET Magazine, SQLServerCurry and DevCurry. He has also written an EBook 51 Recipes using jQuery with ASP.NET Controls. and authored a new one at The Absolutely Awesome jQuery CookBook.

Follow him on twitter @suprotimagarwal


Page copy protected against web site content infringement by Copyscape


User Feedback
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;

Post your comment
Name:  
E-mail: (Will not be displayed)
Comment:
Insert Cancel