<!-- Holds the start node for the navigation. Optional --> <xsl:param name="startNodeId" select="/macro/startNodeId"/> <!-- Holds number of sublevels to generate. Macro parameter is optional. Defaults to one if not supplied --> <xsl:param name="maxDrilldownLevel" select="netaddicts-be:ReadMacroParameter(//macro/maxLevels,'1')"/>
<xsl:template match="/">
<!-- Check whether a start node has been supplied --> <xsl:choose> <xsl:when test="$startNodeId != ''">
<!-- Start building the top navigation from the node supplied by start node id --> <xsl:call-template name="buildTopNavigation"> <xsl:with-param name="navigationNodes" select="umbraco.library:GetXmlNodeById($startNodeId)"/> </xsl:call-template>
</xsl:when> <xsl:otherwise>
<!-- Start building navigation from top level node --> <xsl:call-template name="buildTopNavigation"> <xsl:with-param name="navigationNodes" select="umbraco.library:GetXmlAll()"/> </xsl:call-template>
</xsl:otherwise> </xsl:choose>
</xsl:template>
<!-- Start building the top navigation (first level navigation) --> <xsl:template name="buildTopNavigation"> <xsl:param name="navigationNodes"/>
<!-- Create var for easier reading/processing --> <xsl:variable name="currentProcessedNode" select="."/> <xsl:variable name="currentLevel" select="0"/>
<!-- Check whether node should be visible in first level navigation --> <xsl:if test="string($currentProcessedNode/umbracoNaviHide) != '1'">
<li>
<!-- Build the navigation link using the node currently being processed in the for-each loop --> <xsl:call-template name="buildLink"> <xsl:with-param name="node" select="$currentProcessedNode"/> </xsl:call-template>
<!-- Build next level navigation only if applicable --> <!-- Still need to check whether all child nodes have been set to umbracoHideChildren = 1 whereas umbracoNaviHide = 0 this case would yield an empty ul element --> <xsl:if test="(count($currentProcessedNode/node) > 0) and (string($currentProcessedNode/umbracoHideChildren) != '1') and ($currentLevel < $maxDrilldownLevel)"> <xsl:call-template name="buildNavigation"> <xsl:with-param name="parentNode" select="$currentProcessedNode"/> <xsl:with-param name="level" select="$currentLevel + 1"/> </xsl:call-template> </xsl:if>
</li>
</xsl:if>
</xsl:for-each>
</ul>
</xsl:template>
<!-- A template used for building the non top navigation tree --> <xsl:template name="buildNavigation"> <xsl:param name="parentNode"/> <xsl:param name="level"/>
<ul>a <!-- Iterate over the child nodes--> <xsl:for-each select="$parentNode/* [@isDoc]">
<!-- Create var for easier reading/processing --> <xsl:variable name="currentProcessedNode" select="."/>
<!-- Check whether node should be processed --> <xsl:if test="string($currentProcessedNode/umbracoNaviHide) != '1'">
<li class="child">
<!-- Build the navigation link --> <xsl:call-template name="buildLink"> <xsl:with-param name="node" select="$currentProcessedNode"/> </xsl:call-template>
<!-- Build next level navigation only if applicable; recursive call --> <!-- Still need to check whether all child nodes have been set to umbracoHideChildren = 1 whereas umbracoNaviHide = 0 this case would yield an empty ul element --> <xsl:if test=" (count($currentProcessedNode/node) > 0) and (string($currentProcessedNode/umbracoHideChildren) != '1') and ($level < $maxDrilldownLevel)"> <xsl:call-template name="buildNavigation"> <xsl:with-param name="parentNode" select="$currentProcessedNode"/> <xsl:with-param name="level" select="$level + 1"/> </xsl:call-template> </xsl:if>
</li>
</xsl:if>
</xsl:for-each>
</ul>
</xsl:template>
<!-- A template that builds our navigation link based on node properties --> <xsl:template name="buildLink"> <xsl:param name="node"/>
<xsl:choose>
<!-- Build link to external page --> <xsl:when test="string($node/externalURL) != ''">
<!-- A template that builds a link to an external page --> <xsl:template name="buildExternalLink"> <xsl:param name="node"/>
<!-- <xsl:call-template name ="outputNode"> <xsl:with-param name="currentNode" select="$* [@isDoc]"/> </xsl:call-template> -->
<a> <!-- Set the href attribute --> <xsl:attribute name="href"> <xsl:value-of select="$node/externalURL"/> </xsl:attribute> <!-- Set the target attribute if available from the properties --> <xsl:if test="string($node/externalTarget) != ''"> <xsl:attribute name="target"> <xsl:value-of select="$node/externalTarget"/> </xsl:attribute> </xsl:if> <!-- Set the title attribute if available from the properties --> <xsl:if test="string($node/navTooltip) != ''"> <xsl:attribute name="title"> <xsl:value-of select="string($node/navTooltip)"/> </xsl:attribute> </xsl:if> <!-- Set actual text for the link, either available from the properties or just plain umbraco link--> <xsl:choose> <xsl:when test="string($node/navText) != ''"> <xsl:value-of select="string($node/navText)"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="$node/@nodeName"/> </xsl:otherwise> </xsl:choose> </a>
<!-- <xsl:call-template name ="outputNode"> <xsl:with-param name="currentNode" select="$* [@isDoc]"/> </xsl:call-template> -->
<a> <!-- Set the href attribute based on the redirect supplied --> <xsl:attribute name="href"> <xsl:value-of select="netaddicts-be:FixLink(string($node/umbracoRedirect))"/> </xsl:attribute> <!-- Set the title attribute if available from the properties --> <xsl:if test="string($node/navTooltip) != ''"> <xsl:attribute name="title"> <xsl:value-of select="string($node/navTooltip)"/> </xsl:attribute> </xsl:if> <!-- Set actual text for the link, either available from the properties or just plain umbraco link--> <xsl:choose> <xsl:when test="string($node/navText) != ''"> <xsl:value-of select="string($node/navText)"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="$node/@nodeName"/> </xsl:otherwise> </xsl:choose> </a>
<!-- <xsl:call-template name ="outputNode"> <xsl:with-param name="currentNode" select="$* [@isDoc]"/> </xsl:call-template> -->
<a> <!-- Set the href attribute, either the alias if available, else use NiceUrl() --> <xsl:attribute name="href"> <xsl:choose> <xsl:when test="string($node/umbracoUrlAlias) != ''"> <xsl:value-of select="netaddicts-be:FixLink(string($node/umbracoUrlAlias))"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="umbraco.library:NiceUrl($node/@id)"/> </xsl:otherwise> </xsl:choose> </xsl:attribute> <!-- Set the title attribute if available from the properties --> <xsl:if test="string($node/navTooltip) != ''"> <xsl:attribute name="title"> <xsl:value-of select="string($node/navTooltip)"/> </xsl:attribute> </xsl:if> <!-- Set actual text for the link, either available from the properties or just plain umbraco link--> <xsl:choose> <xsl:when test="string($node/navText) != ''"> <xsl:value-of select="string($node/navText)"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="$node/@nodeName"/> </xsl:otherwise> </xsl:choose> </a>
//Function is taken from XSLTSearch by Douglas Robar from Percipient Studios (http://www.percipientstudios.com/) public string ReadMacroParameter(string value, string defaultValue) { if (value == "") return defaultValue; else return value.Replace(" ", ""); }
//Function fixes a possible wrongly formatted link public string FixLink(string oldLink) { string newLink = string.Empty;
if (!oldLink.StartsWith("/")) newLink += "/"; newLink += oldLink; if (!oldLink.EndsWith(".aspx")) newLink += ".aspx";
<xsl:template match="/"> Startnode: <xsl:value-of select="$startNodeId"/><br /> MAxlevel: <xsl:value-of select="$maxDrilldownLevel"/><br /> <xsl:choose> <xsl:when test="$startNodeId != ''"> <!-- Start building the top navigation from the node supplied by start node id --> <xsl:call-template name="buildTopNavigation"> <xsl:with-param name="navigationNodes" select="umbraco.library:GetXmlNodeById($startNodeId)"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <!-- Start building navigation from top level node --> <xsl:call-template name="buildTopNavigation"> <xsl:with-param name="navigationNodes" select="umbraco.library:GetXmlAll()"/> </xsl:call-template> </xsl:otherwise> </xsl:choose> </xsl:template>
<xsl:template name="buildTopNavigation"> <!-- Start building the top navigation (first level navigation) --> <xsl:param name="navigationNodes"/> NAvigationnodes: <xsl:value-of select="$navigationNodes"/> <ul class="mainNav">
<xsl:for-each select="$navigationNodes/* [@isDoc]"> a <xsl:variable name="currentProcessedNode" select="."/> <xsl:variable name="currentLevel" select="0"/>
<!-- Check whether node should be visible in first level navigation --> <xsl:if test="string($currentProcessedNode/umbracoNaviHide) != '1'"> <li> <!-- Build the navigation link using the node currently being processed in the for-each loop --> <xsl:call-template name="buildLink"> <xsl:with-param name="node" select="$currentProcessedNode"/> </xsl:call-template>
<!-- Build next level navigation only if applicable -->
<!-- A template used for building the non top navigation tree --> <xsl:template name="buildNavigation"> <xsl:param name="parentNode"/> <xsl:param name="level"/>
<ul>a <!-- Iterate over the child nodes--> <xsl:for-each select="$parentNode/* [@isDoc]">
<!-- Create var for easier reading/processing --> <xsl:variable name="currentProcessedNode" select="."/>
<!-- Check whether node should be processed --> <xsl:if test="string($currentProcessedNode/umbracoNaviHide) != '1'">
<li class="child">
<!-- Build the navigation link --> <xsl:call-template name="buildLink"> <xsl:with-param name="node" select="$currentProcessedNode"/> </xsl:call-template>
<!-- Build next level navigation only if applicable; recursive call --> <!-- Still need to check whether all child nodes have been set to umbracoHideChildren = 1 whereas umbracoNaviHide = 0 this case would yield an empty ul element --> <xsl:if test=" (count($currentProcessedNode/node) > 0) and (string($currentProcessedNode/umbracoHideChildren) != '1') and ($level < $maxDrilldownLevel)"> <xsl:call-template name="buildNavigation"> <xsl:with-param name="parentNode" select="$currentProcessedNode"/> <xsl:with-param name="level" select="$level + 1"/> </xsl:call-template> </xsl:if>
</li>
</xsl:if>
</xsl:for-each>
</ul>
</xsl:template>
<!-- A template that builds our navigation link based on node properties --> <xsl:template name="buildLink"> <xsl:param name="node"/>
<a> <!-- Set the href attribute, either the alias if available, else use NiceUrl() --> <xsl:attribute name="href"> <xsl:value-of select="umbraco.library:NiceUrl($node/id)"/> </xsl:attribute> <!-- Set actual text for the link, either available from the properties or just plain umbraco link--> <xsl:choose> <xsl:when test="string($node/navText) != ''"> <xsl:value-of select="string($node/navText)"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="$node/nodeName"/> </xsl:otherwise> </xsl:choose> </a>
</xsl:template>
</xsl:stylesheet>
But now i get this error when saving:
Error occured System.OverflowException: Value was either too large or too small for an Int32. at System.Convert.ToInt32(Double value) at System.Double.System.IConvertible.ToInt32(IFormatProvider provider at System.Convert.ChangeType(Object value, Type conversionType, IFormatProvider provider) at System.Xml.Xsl.Runtime.XmlQueryRuntime.ChangeTypeXsltArgument(XmlQueryType xmlType, Object value, Type destinationType) at System.Xml.Xsl.Runtime.XmlQueryContext.InvokeXsltLateBoundFunction(String name, String namespaceUri, IList`1[] args) at (XmlQueryRuntime {urn:schemas-microsoft-com:xslt-debug}runtime, XPathNavigator node) at (XmlQueryRuntime {urn:schemas-microsoft-com:xslt-debug}runtime, IList`1 navigationNodes) at Root(XmlQueryRuntime {urn:schemas-microsoft-com:xslt-debug}runtime) at Execute(XmlQueryRuntime {urn:schemas-microsoft-com:xslt-debug}runtime) at System.Xml.Xsl.XmlILCommand.Execute(Object defaultDocument, XmlResolver dataSources, XsltArgumentList argumentList, XmlSequenceWriter results) at System.Xml.Xsl.XmlILCommand.Execute(Object defaultDocument, XmlResolver dataSources, XsltArgumentList argumentList, XmlWriter writer) at System.Xml.Xsl.XslCompiledTransform.Transform(IXPathNavigable input, XsltArgumentList arguments, XmlWriter results, XmlResolver documentResolver) at System.Xml.Xsl.XslCompiledTransform.Transform(IXPathNavigable input, XsltArgumentList arguments, TextWriter results) at umbraco.presentation.webservices.codeEditorSave.SaveXslt(String fileName, String oldName, String fileContents, Boolean ignoreDebugging)
Yes, id is still an attribute of whatever element you have in the node variable, so you access it with '@'. I can see where that document might have gotten you though. NodeTypeAlias used to be an attribute of the data element, so you had to do 'data [@nodeTypeAlias='whatever']'. That one attribute is now an element and that was the big change (and a very nice one). Other attributes are still attributes though, so need the @.
creating multi-level navigation in 4.5 schema
I'm having some issues getting multiple level navigation to work with the new xml schema, has anyone got a working example ready?
in the end i would like this to be able to work with a sourcenode to start iterating from, and respecting umbraconavihide...
This is the code that I am using now, but it doesn't go into levels, and doesn't return all nodes but only 1 document type for some reason...
I haven't tried this yet, but it seems like this line should be the problem
Have you tried
I've removed a lot of the complicated xslt and ended up with this:
But now i get this error when saving:
So you're passing an extension expecting an int a bad value. Maybe here
Should be @id instead? Might be time for the debugger to see which line is throwing the exception.
Jeff: are you sure? that's not what I conclude from these examples: http://our.umbraco.org/wiki/reference/xslt/45-xml-schema/xslt-examples-updated-to-new-schema
Yes, id is still an attribute of whatever element you have in the node variable, so you access it with '@'. I can see where that document might have gotten you though. NodeTypeAlias used to be an attribute of the data element, so you had to do 'data [@nodeTypeAlias='whatever']'. That one attribute is now an element and that was the big change (and a very nice one). Other attributes are still attributes though, so need the @.
To create this navigation:
I finally came up with this xslt:
Thank you Rik!
I needed:
For my level 2 check, awesome!
is working on a reply...