Reputation: 557
I have a problem where I have an xml content with different keys needs to be grouped together and displayed, when displayed there is a pagination so I can't display all entries on the same page, I'm using for-each-group for grouping the items, and loop through each current-group() and display its item, the xml is something like this:
<entry>
<key>key1</key>
<value>value1</value>
</entry>
<entry>
<key>key2</key>
<value>value2</value>
</entry>
<entry>
<key>key1</key>
<value>value3</value>
</entry>
<entry>
<key>key1</key>
<value>value4</value>
</entry>
<entry>
<key>key3</key>
<value>value5</value>
</entry>
<entry>
<key>key2</key>
<value>value6</value>
</entry>
<entry>
<key>key4</key>
<value>value7</value>
</entry>
<entry>
<key>key3</key>
<value>value8</value>
</entry>
<entry>
<key>key5</key>
<value>value9</value>
</entry>
<entry>
<key>key1</key>
<value>value10</value>
</entry>
<entry>
<key>key2</key>
<value>value11</value>
</entry>
which should display like:
Page1:
key1
value1
value3
value4
value10
key2
value2
value6
value11
key3
value5
value8
key4
value7
Page2:
key5
value9
the xsl I'm using without pagination is
<xsl:for-each-group select="entry" group-by="key">
<xsl:value-of select="current-grouping-key()"/>
<xsl:for-each select="current-grouping()">
<xsl:apply-templates select="." />
</xsl:for-each>
</xsl:for-each-group>
I need to display only 10 items on each page, how can I get the count of preceding entries of current-grouping()
edit for more info:
I have a variable $size and $offsite, what I'm basically trying to do is something like :
<xsl:if test="$count > $offset and $count <= $offset + $size">
<xsl:apply-templates select="." />
</xsl:if>
where $count would have the count of all items already rendered, ideally if some how I can create a counter similar to position() in for-each but it doesn't restart with each loop of current-group().
if I don't want group items by key, I would have done something like this:
<xsl:for-each select="entry">
<xsl:if test="position() > $offset and position() <= $offset + $size">
<xsl:apply-templates select="." />
</xsl:if>
</xsl:for-each>
but now since I'm using for-each-group, and the entries of each group are looped through individually, how can I keep track of entries that are already rendered from preceding groups.
Upvotes: 1
Views: 1055
Reputation: 122364
You could do it in two stages - first re-order the whole unpaginated list of entries so they are grouped together by key (i.e. in the order that the final output requires), then take the appropriate page "slice" of that sequence to do the actual transformation:
<xsl:variable name="orderedEntries" as="element()*">
<xsl:for-each-group select="entry" group-by="key">
<xsl:sequence select="current-group()" />
</xsl:for-each-group>
</xsl:variable>
<xsl:for-each-group select="$orderedEntries[
position() > $offset and position() <= $offset + $size]"
group-by="key">
<xsl:value-of select="current-grouping-key()"/>
<xsl:for-each select="current-group()">
<xsl:apply-templates select="." />
</xsl:for-each>
</xsl:for-each-group>
This will work even if the page break is part way through a group, e.g. an $offset
and $size
of 5 given your example input would produce
key2
value6
value11
key3
value5
value8
key4
value7
P.S. as Martin points out in a comment, the
<xsl:for-each select="current-group()">
<xsl:apply-templates select="." />
</xsl:for-each>
is for most purposes equivalent to simply
<xsl:apply-templates select="current-group()"/>
(the only difference being in the values of position()
and last()
that the called templates will see)
Upvotes: 2