xslt, every other node, alternate nodes

Alternate nodes

1. Split a long list into groups
2. Detecting every other node
3. Fixed cols with variable rows

1.

Split a long list into groups

Michael Kay

The logic for splitting a list of 100 items into pages of 20 is exactly the same as arranging it in a table with 20 rows. It's basically

<xsl:for-each select="item[position() mod 20 = 1]">
  <page>
    <xsl:for-each 
        select=".|following-sibling::item[position() <20]">
            ....

2.

Detecting every other node

Mike Kay and David Carlisle


> I am trying to apply a different template for every other 
> row, without using JavaScript.

<xsl:template match="row[position() mod 2 = 0]">
<xsl:template match="row[position() mod 2 = 1]">

Or From David C



<xsl:choose>
<xsl:when test="position() mod 2 = 0"> do this ...
<xsl:otherwise> do something else> ....

3.

Fixed cols with variable rows

Warren Hedley

>I have to parse it with XSL into a two column table so that <info> with
> odd-number position goes into the left column and the even number <info>
> into the right column, two <info>'s in each row.
> All suggestions welcome. I can only make it appear in one column, one <info
> in each row.  Wouldn't be so tricky if the number of <info> didn't change.

Warren Hedley replied:

For fixed number of columns, variable number of rows, you can use call-template recursively:

  <xsl:template name="make-row">
  <xsl:param name="cells" select= "count(child::ITEM)"/> <!-- total #cells  -->
    <xsl:param name="cols" select="2"/>  <!--  desired #columns  -->
      <xsl:param name="start" select="1" /> <!--  first cell in this row  -->
	<!--  last cell in this row  -->
	  <xsl:param name="end" select= "$start + $cols"/>
	  <xsl:element name="TR">
	    <xsl:for-each select="child::ITEM[position() >= $start and position() < $end ]">
	      <xsl:element name="TD">
		<xsl:apply-templates/>
	      </xsl:element>
	    </xsl:for-each>
	  </xsl:element>
	  <xsl:if test="$end &lt;= $cells">
	    <xsl:call-template name="make-row">
	      <xsl:with-param name="start" select = "$end"/>
	      <xsl:with-param name="cols" select="$cols"/>
	    </xsl:call-template>
	  </xsl:if>
	</xsl:template>

Another approach, if you're using SAXON, is to use saxon:group with group-by="floor((position() - 1) div $cols)".