How can I split <xsl: foreach> into several parts?
I have a list of elements that I want to split into separate lists of 3. The final result will be something like this:
<ul>
<li>element</li>
<li>element</li>
</ul>
<ul>
<li>element</li>
<li>element</li>
</ul>
<ul>
<li>element</li>
<li>element</li>
</ul>
My XSLT is like this, but it doesn’t work, because I can’t insert </ul>, and I can’t insert a smaller sign ( <).
<ul>
<xsl:for-each select="$myroot/item">
<li></li>
<xsl:if test="position() mod $maxItemsPerColumn = 0">
<!-- I want to close my ul, and start a new one here, but it doesn't work! -->
</xsl:if>
</xsl:for-each>
</ul>
Any ideas? Thanks in advance!
You do not need to do anything like recursion. And good gentleman, don’t even consider using CDATA.
You just need to think like XSLT and ask: "What input element do I want to convert to my output element?"
, ul N item s, N- item, , ul:
<xsl:variable name="n" select="number(4)"/>
<xsl:template match="/">
<output>
<xsl:apply-templates select="/root/item[position() mod $n = 1]"/>
</output>
</xsl:template>
item ul, N-1 :
<xsl:template match="item">
<ul>
<xsl:for-each select=". | following-sibling::item[position() < $n]">
<li>
<xsl:value-of select="."/>
</li>
</xsl:for-each>
</ul>
</xsl:template>
:
<root>
<item>1</item>
<item>2</item>
<item>3</item>
<item>4</item>
<item>5</item>
<item>6</item>
<item>7</item>
<item>8</item>
<item>9</item>
</root>
... , $n 4:
<output>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
<ul>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
</ul>
<ul>
<li>9</li>
</ul>
</output>
, :
<xsl:call-template name="group">
<xsl:with-param name="items" select="$myroot/item" />
</xsl:call-template>
<xsl:template name="group">
<xsl:param name="items" />
<xsl:if test="count($items) > 0">
<ul>
<xsl:for-each select="$items[position() <= 3]">
<li>...</li>
</xsl:for-each>
</ul>
<xsl:call-template name="group">
<xsl:with-param name="items" select="$items[position() > 3]" />
</xsl:call-template>
</xsl:if>
</xsl:template>
, group . group ( , ) <ul> ... </ul>. , . , group .
XSLT - , , (.. disable-output-escaping ), , .
- ( , )
(...)
<xsl:call-template name="recursive">
<xsl:with-param name="root" select="$myroot"/>
<xsl:with-param name="index" select="number(1)"/>
</xsl:call-template>
(...)
<xsl:template name="recursive">
<xsl:param name="root"/>
<xsl:param name="index"/>
<ul>
<li><xsl:value-of select="$root/item[$index]"/></li>
<li><xsl:value-of select="$root/item[$index +1 ]"/></li>
</ul>
<xsl:if test="$root/item[$index+2]">
<xsl:call-template name="recursive">
<xsl:with-param name="root" select="$root"/>
<xsl:with-param name="index" select="$index+2"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:text disable-output-escaping="yes"><![CDATA[</ul>]]></xsl:text>
<xsl:text disable-output-escaping="yes"><![CDATA[<ul>]]></xsl:text>
:
<ul>
<xsl:for-each select="$myroot/item">
<li></li>
<xsl:if test="position() mod $maxItemsPerColumn = 0">
<xsl:text disable-output-escaping="yes"><![CDATA[</ul>]]></xsl:text>
<xsl:text disable-output-escaping="yes"><![CDATA[<ul>]]></xsl:text>
</xsl:if>
</xsl:for-each>
</ul>
: , , , -, -.
Update 2: Yes, I understand why it can be terrible and inspire Nagul-like fear in my peers, and yes, I tried to vote for it myself, but I think this answer may be useful to someone in the future.