Re: Retriving next 10 elements?

Subject: Re: Retriving next 10 elements?
From: Jeni Tennison <mail@xxxxxxxxxxxxxxxx>
Date: Fri, 18 Aug 2000 09:43:01 +0100
Vetrivel,

>   we are using Xml with Xsl for presentaion.In this our requirment is ,If
>we are getting 100 results,in the xml format we want to display 10 at a time
>without going to the database again.I think the xsl should be able to take
>all the 100 results and display 10 each time.please suggest with code if
>possible.

Since you don't give any example XML to work with, I'm going to give a
general answer with a silly example that is:

<list>
  <item>1</item>
  <item>2</item>
  ...
</list>

Note that in this example all the items that you're interested in appear on
the same level: they're siblings.  There is a more general solution where
this isn't the case, but this *is* the case in the vast majority of
situations where people want to group by position, as far as I can tell.

The design pattern for doing this has two stages:
1. select the first of the group
2. during the processing of the first of the group, select the rest of the
group

Selecting the first of the group involves selecting those nodes that have a
position in the set that, when 'mod'ed with the number of elements per
group, evaluates to 1, so generally:

  $nodes[position() mod $group-size = 1]

or with my example:

  item[position() mod 10 = 1]

When you've identified the first of a group, finding the rest of the group
is a matter of looking for the next n siblings, where n is the size of the
group minus 1 or, in other words, those that have a position in the set of
following siblings that is less than the size of the group.  The group
consists of the node you've got (the first in the group) and the next n nodes:

  . | following-sibling::*[position() &lt; $group-size]

or with my example:

  . | following-sibling::item[position() &lt; 10]

You can do the actual processing with either xsl:apply-templates or with
xsl:for-each.  With xsl:apply-templates it looks like:

<xsl:template match="list">
  <xsl:apply-templates select="item[position() mod 10 = 1]"
                       mode="group" />
</xsl:template>

<xsl:template match="item" mode="group">
  <xsl:apply-templates
      select=". | following-sibling::item[position() &lt; 10]" />
</xsl:template>

With xsl:for-each it looks like:

<xsl:template match="list">
  <xsl:for-each select="item[position() mod 10 = 1]">
    <xsl:apply-templates
        select=". | following-sibling::item[position() &lt; 10]" />
  </xsl:for-each>
</xsl:template>

Generally, I would keep the size of the groups that you wanted to generate
in a separate variable or, better, a global parameter, that would allow you
to vary it later on, either by changing the stylesheet at one place or by
passing a different value for the parameter into the stylesheet:

<xsl:param name="group-size" select="10" />

I hope that this helps,

Jeni

Jeni Tennison
http://www.jenitennison.com/



 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread