The problem is that I only need to output the <div id="row"> ... </div> around every 3rd item but if I use the following code I get errors telling me there is no closing element i.e. the "</div>"
<xsl:when test="position() mod 4 = 0 or position() = 1"> <div id="row"> </xsl:when> </xsl:choose>
The way you do this in XSLT demands a somewhat radical shift in thinking, so I'll post the code with comments and hopefully you'll be able to grasp the idea and tweak it to your specific needs:
<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:make="urn:schemas-microsoft-com:xslt"
xmlns:umbraco.library="urn:umbraco.library"
exclude-result-prefixes="umbraco.library make"
>
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes" />
<xsl:param name="currentPage" />
<xsl:variable name="root" select="$currentPage/ancestor-or-self::root" />
<!-- Grab the data to output -->
<xsl:variable name="nodes">
<xsl:copy-of select="$root//*[@nodeType = 1074][not(umbracoNaviHide = 1)]" />
</xsl:variable>
<!-- Enable XPath selection in nodes -->
<xsl:variable name="data" select="make:node-set($nodes)" />
<xsl:template match="/">
<!-- Apply templates to every third document, starting with the first -->
<xsl:apply-templates select="$data/*[position() mod 3 = 1]" mode="row" />
</xsl:template>
<!-- Template to start a row -->
<xsl:template match="*[@nodeType = 1074]" mode="row">
<div class="row">
<!-- Now render this document and the following 2 -->
<xsl:apply-templates select=". | following-sibling::*[@nodeType = 1074][position() < 3]" mode="col" />
</div>
</xsl:template>
<!-- Template for a column -->
<xsl:template match="*[@nodeType = 1074]" mode="col">
<div class="col">
<!-- Redefine class for every third item -->
<xsl:if test="position() mod 3 = 0">
<xsl:attribute name="class">col last</xsl:attribute>
</xsl:if>
<xsl:value-of select="@nodeName" />
</div>
</xsl:template>
</xsl:stylesheet>
Yep - methinks too. Also, it's actually because (as you may already know) I do all my XSLT coding on my MacBook Pro, so that prefix is actually mapped to "http://exslt.org/common" when I code. I just swap the MS-namespace in before pasting here :-)
Thanks Chriztian. I was resigned to trying to do it in a user control as I don't think I could have worked it out myself.
I don't know about anyone else, but I find XSLT makes as much sense as spaghetti with it's slashes and colons, and now 4.5 uses a different way doing everything just as I was getting used to it (in my own limited way ;-))
Since I never really understood the method Chriztian posted, I typically follow your attempted approach, but get around the closing tag error by encoding it so it's not detected as a tag by the parser. Probably not the right way of doing things but it's more of a quick fix/hack:
<xsl:when test="position() mod 4 = 0 or position() = 1"> <xsl:text disable-output-escaping="yes"><div id="row"></xsl:text> </xsl:when>
...
<xsl:when test="position() mod 4 = 0 or position() = 1"> <xsl:text disable-output-escaping="yes"></div></xsl:text> </xsl:when>
Going to try Chriztian's method next time - his comments make it much easier to follow :)
Way to go Scott! On the very day they release the "XSLT-Obliterator" (V5, that is) you say, "Nay - I'll use this awesome snippet here and be done with it."
Adding <div> around every 3rd item returned from GetXmlAll()
Wonder if anyone can help me. I need to output some html (that is already in an existing system) similar to the following:
<div id="row">
<div class="col">
</div>
<div class="col">
</div>
<div class="col last">
</div>
</div>
I am using GetXmlAll() and filtering the nodeType i.e.
<xsl:for-each select="umbraco.library:GetXmlAll()//* [@nodeType='1074' and umbracoNaviHide != '1']">
and am using the following code to set the "col last" class on the 3rd item i.e.
<xsl:if test="position() mod 3 = 0">
<xsl:attribute name="class">
<xsl:text>col last</xsl:text>
</xsl:attribute>
</xsl:if>
The problem is that I only need to output the <div id="row"> ... </div> around every 3rd item but if I use the following code I get errors telling me there is no closing element i.e. the "</div>"
<xsl:when test="position() mod 4 = 0 or position() = 1">
<div id="row">
</xsl:when>
</xsl:choose>
Any help would be much appreciated.
Hi Kevin,
The way you do this in XSLT demands a somewhat radical shift in thinking, so I'll post the code with comments and hopefully you'll be able to grasp the idea and tweak it to your specific needs:
/Chriztian
Chriztian, love how you rename the msxml namespace as "make" reads better ;)
@Pete:
Yep - methinks too. Also, it's actually because (as you may already know) I do all my XSLT coding on my MacBook Pro, so that prefix is actually mapped to "http://exslt.org/common" when I code. I just swap the MS-namespace in before pasting here :-)
/Chriztian
Thanks Chriztian. I was resigned to trying to do it in a user control as I don't think I could have worked it out myself.
I don't know about anyone else, but I find XSLT makes as much sense as spaghetti with it's slashes and colons, and now 4.5 uses a different way doing everything just as I was getting used to it (in my own limited way ;-))
Thanks again,
Kevin
Hang in there Kevin; the 4.5 XML format makes it so much easier to "read" what's going on, trust me :-)
But you'll always have all the smart heads in the entire Umbraco Community to ask when stuff goes up in smoke...
/Chriztian
Since I never really understood the method Chriztian posted, I typically follow your attempted approach, but get around the closing tag error by encoding it so it's not detected as a tag by the parser. Probably not the right way of doing things but it's more of a quick fix/hack:
...
Going to try Chriztian's method next time - his comments make it much easier to follow :)
Chriztian ,
Thanks so much for that code snippet! I was able to tweak it a little bit to add a div around every fourth item.
Way to go Scott! On the very day they release the "XSLT-Obliterator" (V5, that is) you say, "Nay - I'll use this awesome snippet here and be done with it."
Thanks :-)
/Chriztian
Thanks Chriztian :)
is working on a reply...