Using XSLT to display an ASP.net sitemap without using tables
The quick and easy way of displaying an ASP.net site map
(web.sitemap
) in an ASP.net page is to use a TreeView
control bound to a SiteMapDataSource
component as shown in the
following example:
<asp:SiteMapDataSource runat="server" ID="siteMapDataSource" EnableViewState="False" ShowStartingNode="False" />
<asp:TreeView runat="server" ID="siteMapTreeView" DataSourceID="siteMapDataSource" EnableClientScript="False" EnableViewState="False" ShowExpandCollapse="False"></asp:TreeView>
Which results in a mass of nested tables, in-line styles, and generally messy mark-up.
With just a little more effort however, you can display the sitemap using a XSLT transform, resulting in slim, clean and configurable mark-up - and not a table to be seen.
This approach can be used with both Web Forms and MVC.
This article assumes you already have a pre-made ASP.net sitemap file.
Defining the XSLT
Add a new XSLT File to your project. In this case, it's
named sitemap.xslt
.
Next, paste in the mark-up below.
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:map="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0" exclude-result-prefixes="map">
<xsl:output method="xml" encoding="utf-8" indent="yes"/>
<xsl:template name="mapNode" match="map:siteMap">
<ul>
<xsl:apply-templates/>
</ul>
</xsl:template>
<xsl:template match="map:siteMapNode">
<li>
<a href="http://cyotek.com{substring(@url, 2)}" title="{@description}">
<xsl:value-of select="@title"/>
</a>
<xsl:if test="map:siteMapNode">
<xsl:call-template name="mapNode"/>
</xsl:if>
</li>
</xsl:template>
</xsl:stylesheet>
Note: As generally all URLs in ASP.net site maps start with
~/
, the href
tag in the above example has been customized to
include the domain http://cyotek.com at the start, then use
the XSLT substring
function to strip the ~/
from the start
of the URL. Don't forget to modify the URL to point to your own
domain!
Declaratively transforming the document
If you are using Web forms controls, then this may be the more convenient approach for you.
Just add the XML component to your page, and set the
DocumentSource
property to the name of the sitemap, and the
TransformSource
property to the name of your XSLT file.
<asp:Xml runat="server" ID="xmlSiteMapViewer" DocumentSource="~/web.sitemap" TransformSource="~/sitemap.xslt" />
Programmatically transforming the document
The ASP.net XML control doesn't need to be inside a server side
form
tag, so you can use the exact same code above in your
MVC views.
However, if you want to do this programmatically, the following code works too.
var xmlFileName = Server.MapPath("~/web.sitemap");
var xslFileName = Server.MapPath("~/sitemap.xslt");
var result = new System.IO.StringWriter();
var transform = new System.Xml.Xsl.XslCompiledTransform();
transform.Load(xslFileName);
transform.Transform(xmlFileName, null, result);
Response.Write(result.ToString());
The result
The output of the transform will be simple series of nested unordered lists, clean and ready to be styled with CSS. And for little more effort than it took to do the original tree view solution.
With a bit more tweaking you can probably expand this to show only a single branch, useful for navigation within a section of a website, or creating breadcrumb trails.
Update History
- 2010-02-06 - First published
- 2020-11-21 - Updated formatting
Leave a Comment
While we appreciate comments from our users, please follow our posting guidelines. Have you tried the Cyotek Forums for support from Cyotek and the community?
Comments
Mohsen Mirshahreza
#
Hi It is a good idea. But when I use the sample in Declaratively or Programmatically there is no result to display!!! how we can show transformed content to asp:lable ? Thanks Mohsen
Richard Moss
#
Mohsen,
Without more information I can't say why it doesn't work for you... we use the same code on the cyotek.com website and it works well for us.
In regards to outputting to a label, you could change
[csharp]Response.Write(result.ToString());[/csharp]
into something like
[csharp]Label1.Text = result.ToString();[/csharp]
from your Page_Load event, OnLoad override etc.
Hope this helps.
Regards; Richard Moss
alam
#
How to bind the declarative xml onto sitemappath? Thanks