Thanks a lot for your reply :-) While it makes sense to me with those three templates, I'm still a bit on the blank side when it comes to actually getting any values in the select element. Do you have a hint for where/when to loop through the node collection?
If your $root node (1071) is a wrapper for the <Countries> nodes, then it should work (and it's best to say $root/Countries intead of $root/* because the latter will process properties of the $root node too, if any, which may give you some extra unintended output).
My guess would be that there's maybe an extra node between $root and the Countries elements (e.g. $root/Settings/Countries) ?
There's no extra node/level between the root node and the countries node. The problem was that the Countries template was never called. Had to use mode="Countries" for that :-) However, I can't get the Destination template to work, which is quite weird because i'm calling it the same way as the Countries template.
My code so far (have to replace the GetXmlNodeById() with a parameter though ;-))
Sorry about the formatting - seems we're missing the 'Code' option in the RTE :-/
So, going the the above code, shouldn't I be able to call the Destinations template with the current Country node by: ./Destination ? Or have I missed something?
I'd just like to clarify the use of the mode attribute vs. the match attribute on the template element:
The match attribute needs to reference an element name from the XML, so in your case you could say:
<xsl:template match="Page">
instead of:
<xsl:template match="*" mode="Countries">
and then take the mode="Countries" out of the apply-templates statement.
Likewise for the "destinations" template, of course.
The mode attribute is normally used when you need more than one template for the same element, or when a template could be used for any element (which is where you'd normally use match="*" mode="something-clever").
So just to be hyper-pedantic, I'll leave you with this (changed stuff highlighted):
Thank you so much for clarifying, Chriztian! :-) Never really got my head around templates in XSLT, but your example above makes it absolutely clear - feels great to finally grasp it.
Rendering structure in a select element
Hi all,
I'm having a bit of trouble when trying to render a part of my sites structure in a html select box. My structure looks like this:
and my select box should be like this:
I've got the following XSLT at the moment:
This "works", but since it's basically a nested for loop (which is disgusting in itself!) it creates an empty option for every parent node.
Anyone got any hints on this? :-) Will be greatly appreciated!
All the best,
Bo
Here's something to get you going with templates:
/Chriztian
Hi Chriztian,
Thanks a lot for your reply :-) While it makes sense to me with those three templates, I'm still a bit on the blank side when it comes to actually getting any values in the select element. Do you have a hint for where/when to loop through the node collection?
Thanks again!
- Bo
Hi Bo,
Imagine a structure like this:
Then I'd do something like this in the macro:
This assumes your "Home" node is at level 1 (very common, you know).
** If you know the "Tags" node is a direct child of the Home node, remove the extra slash, so the apply-templates instruction goes like this:
- which will be faster...
Let me know if you still need help getting it to work.
/Chriztian
Hi Chriztian and thanks again for your input! :-) greatly appreciated!
I'm having this code now, but I'm not sure the optgroup template is ever called(?)
<xsl:param name="currentPage"/>
<xsl:variable name="root" select="umbraco.library:GetXmlNodeById(1071)" />
<xsl:template match="/">
<select>
<xsl:apply-templates select="$root/*"></xsl:apply-templates>
</select>
</xsl:template>
<xsl:template match="Countries">
<optgroup label="{@nodeName}">
<xsl:apply-templates select="Destinations"></xsl:apply-templates>
</optgroup>
</xsl:template>
<xsl:template match="Destinations">
<option>
<xsl:value-of select="@nodeName"/>
</option>
</xsl:template>
Seems I'm having some serious trouble grasping the concept of templates ;-) I'm sure I'm doing something wrong here?
Thanks again,
- Bo
Hi Bo,
Good to see you hangin' in there :-)
If your $root node (1071) is a wrapper for the <Countries> nodes, then it should work (and it's best to say $root/Countries intead of $root/* because the latter will process properties of the $root node too, if any, which may give you some extra unintended output).
My guess would be that there's maybe an extra node between $root and the Countries elements (e.g. $root/Settings/Countries) ?
/Chriztian
Hi again Chriztian,
There's no extra node/level between the root node and the countries node. The problem was that the Countries template was never called. Had to use mode="Countries" for that :-) However, I can't get the Destination template to work, which is quite weird because i'm calling it the same way as the Countries template.
My code so far (have to replace the GetXmlNodeById() with a parameter though ;-))
<xsl:variable name="root" select="umbraco.library:GetXmlNodeById(1071)" />
<xsl:template match="/">
<select>
<option>Vælg destination</option>
<xsl:apply-templates select="$root/Page" mode="Countries"></xsl:apply-templates>
</select>
</xsl:template>
<xsl:template match="*" mode="Countries">
<option label="{@nodeName}">
<xsl:apply-templates select="./Destination" mode="Destinations"></xsl:apply-templates>
</option>
</xsl:template>
<xsl:template match="*" mode="Destinations">
<option>
<xsl:value-of select="@nodeName"/>
</option>
</xsl:template>
Sorry about the formatting - seems we're missing the 'Code' option in the RTE :-/
So, going the the above code, shouldn't I be able to call the Destinations template with the current Country node by: ./Destination ? Or have I missed something?
Thanks again!
- Bo
Alright, finally got it.. and I'm so unbelievable embarrassed about the mistake ;-)
The final solution:
<xsl:template match="/">
<select class="destination-dropdown">
<option>Vælg destination</option>
<xsl:apply-templates select="$root/Page" mode="Countries"></xsl:apply-templates>
</select>
</xsl:template>
<xsl:template match="*" mode="Countries">
<option value="{umbraco.library:NiceUrl(@id)}" class="dd-country-name" label="{@nodeName}">
<xsl:apply-templates select="./destination" mode="Destinations"></xsl:apply-templates>
</option>
</xsl:template>
<xsl:template match="*" mode="Destinations">
<option value="{umbraco.library:NiceUrl(@id)}">
<xsl:value-of select="@nodeName"/>
</option>
</xsl:template>
My grand mistake was to spell "destinations" with lowercase and not "Destinations" /major-golfclap.
Thanks Chriztian for your help and patience! ;-)
Hi Bo,
You're welcome - no worries.
I'd just like to clarify the use of the mode attribute vs. the match attribute on the template element:
The match attribute needs to reference an element name from the XML, so in your case you could say:
instead of:
and then take the mode="Countries" out of the apply-templates statement.
Likewise for the "destinations" template, of course.
The mode attribute is normally used when you need more than one template for the same element, or when a template could be used for any element (which is where you'd normally use match="*" mode="something-clever").
So just to be hyper-pedantic, I'll leave you with this (changed stuff highlighted):
/Chriztian
Thank you so much for clarifying, Chriztian! :-) Never really got my head around templates in XSLT, but your example above makes it absolutely clear - feels great to finally grasp it.
Now.. back to razor and umbraco 4.7! ;-) /teasing
- Bo
is working on a reply...