[XSL-LIST Mailing List Archive Home] [By Thread] [By Date]

Re: [xsl] document function cached?


Subject: Re: [xsl] document function cached?
From: Louis-Dominique Dubeau <ldd@xxxxxxxxxxxx>
Date: Mon, 11 Feb 2013 11:27:53 -0500

On Mon, 2013-02-11 at 16:58 +0100, Michel Hendriksen wrote:

> I would want to match against the position of the node within
> the predicate,
> like in position(current()).

position() does not take a parameter; it already returns the position of
the current node. Typically, the solution to foo[position()] is to
figure out what position one cares about and save that into a variable
and then have foo[$var].

> Its the context switch that makes it weird/meaningless to use
> position() as I did.

Yes, I think understanding the issue of context switches is really key
here. I actually have a working example of a piece of code where it
would be tempting to use foo[position()]. It transforms a table like:

<table>
  <headings>
    <cell>Name</cell><cell>Exam number</cell><cell>Score</cell>
  </headings>
  <row><cell>Alice</cell><cell>001</cell><cell>100</cell></row>
  <row><cell>Bob</cell><cell>010</cell><cell>50</cell></row>
</table>

To:

<list>
  <item>Name: Alice, Exam number: 001, Score: 100</item>
  <item>Name: Bob, Exam number: 010, Score: 50</item>
</list>

Basically, it takes the table and merges the column headings with the
cell data of regular rows to form a list. The important template is this
one:

  <xsl:template match="row/cell">
    <xsl:variable name="col" select="position()"/>
    <!-- It is not possible to use position() instead of $col in the
         next select. -->
    <xsl:apply-templates select="../../headings/cell[$col]"/>: <xsl:apply-templates select="node()"/>
    <xsl:if test="following-sibling::*">
      <xsl:text>, </xsl:text>
    </xsl:if>
  </xsl:template>

One might be tempted to have cell[position()] in this statement:

<xsl:apply-templates select="../../headings/cell[$col]"/>

but this would be exactly the problem we've talked about. The solution
is to save the position I care about in a variable and use the variable
in the predicate. At the time the variable is declared, position() means
what I want it to mean, i.e. the position of the cell element among all
cell elements in the row.

Complete code follows my signature. 

Louis

<xsl:stylesheet 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    version="2.0">

  <!-- Run this file with position2-data.xml. -->
  <xsl:output method="xml"/>

  <xsl:template match="row/cell">
    <xsl:variable name="col" select="position()"/>
    <!-- It is not possible to use position() instead of $col in the
         next select. -->
    <xsl:apply-templates select="../../headings/cell[$col]"/>: <xsl:apply-templates select="node()"/>
    <xsl:if test="following-sibling::*">
      <xsl:text>, </xsl:text>
    </xsl:if>
  </xsl:template>

  <xsl:template match="table">
    <list>
      <xsl:apply-templates select="row"/>
    </list>
  </xsl:template>

  <xsl:template match="row">
    <item>
      <xsl:apply-templates select="*"/>
    </item>
  </xsl:template>

  <xsl:template match="headings/cell">
    <xsl:apply-templates select="node()"/>
  </xsl:template>

  <xsl:template match="node()">
    <xsl:copy>
      <xsl:apply-templates select="node()"/>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>


Current Thread