How Do I Modify Sitemap Template to Use Different HTML Tags for Each Level?
Hi All,
I'm brand new to Umbraco and XSLT, etc so trying to get my head around everything. I want to modify the Sitempap template to display nodes from levels 1, 2 and 3 but I want to assign HTML tags to each level so I can format each level differently for layout purposes.
For Level 1 I want to put each node inside its own <li> tag
For Level 2 I want to put each node inside its own a <strong> tag
For Level 3 I want to put each node inside its own <p> tag
Is this possible. I know some people might think this is uneccessary but I want to make it work if it can be done.
Sorry for the extra post but I just to clarify the above. The HTML outputted for Level 3 nodes should be within the corresponding Level 2 node which in turn should be within the corresponding Level 1 node (as the Sitemap template already does). I want to use the different HTML tags for each level so I can make the appearance of each node different from other nodes in another level. Is that clear enough? (been a long day)
Any reason you're not "just" putting a CSS class containing the level number on them?
Anyways - the easiest way of doing stuff like this, is to use match templates and just define separate templates for the misc. levels - something like this:
<!-- Template for building the link and processing children --> <xsl:templatematch="*[@isDoc]"mode="link"> <ahref="{umb:NiceUrl(@id)}"> <xsl:value-ofselect="name()"/> </a> <xsl:iftest="*[@isDoc][not(umbracoNaviHide = 1)]"> <xsl:apply-templatesselect="*[@isDoc][not(umbracoNaviHide = 1)]"/> </xsl:if> </xsl:template>
<!-- Template for hidden nodes --> <xsl:templatematch="*[@isDoc][umbracoNaviHide = 1]"priority="1"> <!-- No output --> </xsl:template>
Thanks for the reply Chriztian. I playing around with the suggestions you posted above but I'm using Umbraco 4.7 and wondered if the above is for earlier versions? If so, what do I need to change in the above?
The above code is for 4.5+ but using the new schema, so if you're on an upgraded version and you're still on the old schema it won't work - let me know, and I'll create a working version for you.
(Open the Umbraco.config file and see if it's stuffed with <node> elements - then it's the old version)
Thanks again Chriztian. I realized there were a few issues with spaces missing in the code above but missed the '@' symbol I needed to add on level 2 template match line. I'm playing again now and made a little progress. Not there yet but a good learning exercise. I think I will need a little more help soon.
<xsl:param name="currentPage"/> <!-- Select the top node in the Sitemap --> <xsl:variable name="siteRoot" select="$currentPage/ancestor-or-self::*[@level = 1]"/>
<xsl:template match="/"> <!-- Start by processing the top node --> <xsl:apply-templates select="$siteRoot"/> </xsl:template>
I can't seem to get the <div> tags placed where I want them and I also want to add the "main" class to the links in the above HTML. I'm having to convert an existing site to use Umbraco and their dropdown menu needs to use this HTML (not my choice I'm afraid). Also, for some reason the XSLT above is adding some content from the child product pages (eg "0Bedroom Furniture Products" ) and I don't know why.
Hope I'm not causing you a lot of hassle and I appreciate your help.
Alright - starting from the top with your "target" HTML, working through the various templates, got us to this:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:umb="urn:umbraco.library"
exclude-result-prefixes="umb"
>
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
<xsl:param name="currentPage" select="//Website" />
<!-- Select the top node in the Sitemap -->
<xsl:variable name="siteRoot" select="$currentPage/ancestor-or-self::*[@level = 1]"/>
<xsl:template match="/">
<!-- Start by processing the top node -->
<xsl:apply-templates select="$siteRoot"/>
</xsl:template>
<!-- Level 1 nodes -->
<xsl:template match="*[@isDoc][@level = 1]">
<ul id="mega">
<xsl:apply-templates select="*[@isDoc][not(umbracoNaviHide = 1)]" />
</ul>
</xsl:template>
<!-- Level 2 nodes -->
<xsl:template match="*[@isDoc][@level = 2]">
<li class="dropdownsoftware">
<strong><xsl:apply-templates select="." mode="link" /></strong>
<!-- We need this test to not get an empty <div> if no children -->
<xsl:if test="*[@isDoc][not(umbracoNaviHide = 1)]">
<div>
<xsl:apply-templates />
</div>
</xsl:if>
</li>
</xsl:template>
<!-- Level 3 nodes -->
<xsl:template match="*[@isDoc][@level = 3]">
<strong><xsl:apply-templates select="." mode="link"/></strong>
<xsl:apply-templates />
</xsl:template>
<!-- Level 4 nodes -->
<xsl:template match="*[@isDoc][@level = 4]">
<p>
<xsl:apply-templates select="." mode="link"/>
</p>
</xsl:template>
<!-- Template for building the links -->
<xsl:template match="*[@isDoc]" mode="link">
<a href="umb:NiceUrl(@id)">
<xsl:if test="@level = 2"><xsl:attribute name="class">main</xsl:attribute></xsl:if>
<xsl:value-of select="@nodeName"/>
</a>
</xsl:template>
<!--
Template for nodes to hide:
* Nodes with umbracoNaviHide checked
* Properties (have no isDoc attribute)
* Content pages (level 4+)
-->
<xsl:template match="*[@isDoc][umbracoNaviHide = 1] | *[not(@isDoc)] | *[@isDoc][@level > 4]" priority="1">
<!-- No output -->
</xsl:template>
</xsl:stylesheet>
It's really just a matter of seeing which ones need to generate a wrapper, and which needn't - the key to stuff like this is the apply-templates instruction, which (if no selection is specified) will simply look at where it is (e.g. on a level 1 node) and collect all the childnodes (elements and text/comment nodes) and look for templates that match those.
By specifying the right templates, the whole thing writes itself :-)
Chriztian, you're a star. Hopefully I'll get the hang of this soon. Your help is opening my eyes. I found one problem with the links not working but realized I needed to add {} to the <a href part.
Seems to be working well - many thanks. I can go to bed now.
How Do I Modify Sitemap Template to Use Different HTML Tags for Each Level?
Hi All,
I'm brand new to Umbraco and XSLT, etc so trying to get my head around everything. I want to modify the Sitempap template to display nodes from levels 1, 2 and 3 but I want to assign HTML tags to each level so I can format each level differently for layout purposes.
For Level 1 I want to put each node inside its own <li> tag
For Level 2 I want to put each node inside its own a <strong> tag
For Level 3 I want to put each node inside its own <p> tag
Is this possible. I know some people might think this is uneccessary but I want to make it work if it can be done.
Thanks in advance!
Sorry for the extra post but I just to clarify the above. The HTML outputted for Level 3 nodes should be within the corresponding Level 2 node which in turn should be within the corresponding Level 1 node (as the Sitemap template already does). I want to use the different HTML tags for each level so I can make the appearance of each node different from other nodes in another level. Is that clear enough? (been a long day)
Hi Adam,
Any reason you're not "just" putting a CSS class containing the level number on them?
Anyways - the easiest way of doing stuff like this, is to use match templates and just define separate templates for the misc. levels - something like this:
/Chriztian
Thanks for the reply Chriztian. I playing around with the suggestions you posted above but I'm using Umbraco 4.7 and wondered if the above is for earlier versions? If so, what do I need to change in the above?
Cheers
Hi Adam,
The above code is for 4.5+ but using the new schema, so if you're on an upgraded version and you're still on the old schema it won't work - let me know, and I'll create a working version for you.
(Open the Umbraco.config file and see if it's stuffed with <node> elements - then it's the old version)
/Chriztian
Thanks again Chriztian. I realized there were a few issues with spaces missing in the code above but missed the '@' symbol I needed to add on level 2 template match line. I'm playing again now and made a little progress. Not there yet but a good learning exercise. I think I will need a little more help soon.
Cheers!
Adam
Ah - I can see the missing stuff now - the code view isn't always top dollar here. Might be because I edited it...
/Chriztian
No worries Chriztian.
Right, I've made some more progress but hit a brick wall due to my lack of knowledge and coder brain. Anyway, I am using the following XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:umb="urn:umbraco.library"
exclude-result-prefixes="umb"
>
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
<xsl:param name="currentPage"/>
<!-- Select the top node in the Sitemap -->
<xsl:variable name="siteRoot" select="$currentPage/ancestor-or-self::*[@level = 1]"/>
<xsl:template match="/">
<!-- Start by processing the top node -->
<xsl:apply-templates select="$siteRoot"/>
</xsl:template>
<!-- Level 1 nodes -->
<xsl:template match="*[@isDoc][@level = 1]">
<ul id="mega">
<xsl:apply-templates select="." mode="link"/>
</ul>
</xsl:template>
<!-- Level 2 nodes -->
<xsl:template match="*[@isDoc][@level = 2]">
<li class="dropdownsoftware">
<strong>
<xsl:apply-templates select="." mode="link"/>
</strong>
</li>
</xsl:template>
<!-- Level 3 nodes -->
<xsl:template match="*[@isDoc][@level = 3]">
<strong>
<xsl:apply-templates select="." mode="link"/>
</strong>
</xsl:template>
<!-- add DIV -->
<xsl:template match="*[@isDoc][@level = 3]">
<div>
<xsl:apply-templates select="." mode="link"/>
</div>
</xsl:template>
<!-- Level 4 nodes -->
<xsl:template match="*[@isDoc][@level = 4]">
<p>
<xsl:apply-templates select="." mode="link"/>
</p>
</xsl:template>
<!-- Template for building the link and processing children -->
<xsl:template match="*[@isDoc]" mode="link">
<a href="{umb:NiceUrl(@id)}">
<xsl:value-of select="@nodeName"/>
</a>
<xsl:if test="*[@isDoc][not(umbracoNaviHide = 1)]">
<xsl:apply-templates select="*[@isDoc][not(umbracoNaviHide = 1)]"/>
</xsl:if>
</xsl:template>
<!-- Template for hidden nodes -->
<xsl:template match="*[@isDoc][umbracoNaviHide = 1]" priority="1">
<!-- No output -->
</xsl:template>
</xsl:stylesheet>
The XSLT above is generating the following HTML:
which is not far off but I need some help so that the XSLT will generate the following HTML instead:
I can't seem to get the <div> tags placed where I want them and I also want to add the "main" class to the links in the above HTML. I'm having to convert an existing site to use Umbraco and their dropdown menu needs to use this HTML (not my choice I'm afraid). Also, for some reason the XSLT above is adding some content from the child product pages (eg "0Bedroom Furniture Products" ) and I don't know why.
Hope I'm not causing you a lot of hassle and I appreciate your help.
Adam
Hi Adam,
Alright - starting from the top with your "target" HTML, working through the various templates, got us to this:
It's really just a matter of seeing which ones need to generate a wrapper, and which needn't - the key to stuff like this is the apply-templates instruction, which (if no selection is specified) will simply look at where it is (e.g. on a level 1 node) and collect all the childnodes (elements and text/comment nodes) and look for templates that match those.
By specifying the right templates, the whole thing writes itself :-)
Let me know how it goes.
/Chriztian
/Chriztian
Chriztian, you're a star. Hopefully I'll get the hang of this soon. Your help is opening my eyes. I found one problem with the links not working but realized I needed to add {} to the <a href part.
Seems to be working well - many thanks. I can go to bed now.
is working on a reply...