Search

Grouping items for one level deep is easy. But 2 levels, using matched templates? I only managed with loop iterator.

XML:

<articles>
    <entry id="1">...</entry>
    <entry id="2">...</entry>
    <entry id="3">...</entry>
    ...
</articles>

Desired output:

<div class="level-1">
    <div class="level-2">
        article-1
        article-2
        article-3
    </div>
    <div class="level-2">
        article-4
        article-5
        article-6
    </div> 
</div>
<div class="level-1">
    <div class="level-2">
        article-7
        article-8
        article-9
    </div>
    ... 
</div>
...

When trying to group for 2 levels:

<xsl:apply-templates select="articles/entry[ position() mod 6 = 1 ]" mode="level-1" />

<xsl:template match="articles/entry" mode="level-1">
    <div class="level-1">
        <xsl:apply-templates select="following-sibling::entry[ position() mod 3 = 1 and position() &lt; 6 ]" mode="level-2" />
    </div>
</xsl:template>

<xsl:template match="entry" mode="lista-ablume-foto_group">
    <div class="level-2">
        <xsl:apply-templates select=". | following-sibling::entry[position() &lt; 3]" mode="article" />
    </div>
</xsl:template>

<xsl:template match="entry" mode="article">
    article-<xsl:value-of select="@id" />
</xsl:template>

I'm losing the first element in selection:

<div class="level-1">
    <div class="level-2">
        article-2
        article-3
        article-4
    </div>
    <div class="level-2">
        article-4
            ...
    </div>
</div>
...

If I change this

<xsl:apply-templates select="following-sibling::entry[ position() mod 3 = 1 and position() &lt; 6 ]" mode="level-2" />

to this (to add the first element)

<xsl:apply-templates select=". | following-sibling::entry[ position() mod 3 = 1 and position() &lt; 6 ]" mode="level-2" />

I'm getting loads of duplicates ...

Any ideas? Thank you.

The following XSLT should do the trick:

<xsl:apply-templates select="articles/entry[position() mod 6 = 1]" mode="level-1" />

<xsl:template match="articles/entry" mode="level-1">
    <div class="level-1">
        <xsl:apply-templates select=". | following-sibling::entry[3]" mode="level-2" />
    </div>
</xsl:template>

<xsl:template match="entry" mode="level-2">
    <div class="level-2">
        <xsl:apply-templates select=". | following-sibling::entry[position() &lt; 3]" mode="article" />
    </div>
</xsl:template>

<xsl:template match="entry" mode="article">
    article-<xsl:value-of select="@id" />
</xsl:template>

Ha ! Nice one :D Noted down ... Thanks a lot !

I noticed this trick works for a 2*div.level-2. But what if I need 5*div.level-2 inside div.level-1 ?

<div class="level-1">
    <div class="level-2">
        article-1
            ...
    </div>
    <div class="level-2">
        article-6
            ...
    </div>

    <div class="level-2">
        article-11
            ...
    </div>
    ...
</div>

This won't work:

<xsl:apply-templates select=". | following-sibling::entry[ position() mod 3 = 1 ]" mode="level-2" />

Update

Got it working with

<xsl:apply-templates select=". | following-sibling::entry[ position() mod 3 = 0 and position() &lt; 6 ]" mode="level-2" />

Understood it now. Well, at least I learned to use the FOR iterator :)

Create an account or sign in to comment.

Symphony • Open Source XSLT CMS

Server Requirements

  • PHP 5.3-5.6 or 7.0-7.3
  • PHP's LibXML module, with the XSLT extension enabled (--with-xsl)
  • MySQL 5.5 or above
  • An Apache or Litespeed webserver
  • Apache's mod_rewrite module or equivalent

Compatible Hosts

Sign in

Login details