Re: [xsl] XSLT recursion problem

Subject: Re: [xsl] XSLT recursion problem
From: Geert Josten <Geert.Josten@xxxxxxxxxxx>
Date: Wed, 28 Sep 2005 10:26:57 +0200
The real problem is that I don't want to have to know anything about <sometag>. That is, I would be free to use (and nest!) whatever non-proprietary tag inside my <repeat>, without modifing it.
Probably there's no way in XSLT 1.0 (if it is, why creating tunnel in 2.0 ;) , but if you see another solution...

Hi Paolo,


I think you can make this work when you do not interprete and execute your ax template with XSL directly, but write an XSL that will turn you ax template into executable XSL and execute that in a second pass. That way you can use an adapted 'default' template to 'tunnel' the parameters from the ax:repeat template to the ax:items template. I guess something like:

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
    xmlns:ax-xsl="http://www.w3.org/1999/XSL/TransformAlias";
    xmlns:ax="..."
    exclude-result-prefixes="ax"
>

<xsl:namespace-alias stylesheet-prefix="ax-xsl" result-prefix="xsl"/>

  <xsl:output method="xml"
    version="1.0" encoding="utf-8" indent="yes" />

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

  <!-- identity transform -->
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()" />
    </xsl:copy>
  </xsl:template>

  <xsl:template match="ax:repeat">
    <xsl:param name="current-position" select="1" />
    <xsl:param name="max" select="count(//ax:items[1]/ax:item)" />

    <xsl:choose>
      <xsl:when test="$current-position > $max" />
      <xsl:otherwise>
        <xsl:apply-templates select="node()" mode="repeat">
          <xsl:with-param name="current-position" select="$current-position"/>
        </xsl:apply-templates>

        <xsl:apply-templates select=".">
          <xsl:with-param name="current-position" select="$current-position + 1"/>
          <xsl:with-param name="max" select="$max"/>
        </xsl:apply-templates>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <!-- identity transform with parameters for repeat -->
  <xsl:template match="@*|node()" mode="repeat">
    <xsl:param name="current-position" />
    <xsl:param name="max" />

    <xsl:copy>
      <xsl:apply-templates select="@*|node()" mode="repeat">
        <xsl:with-param name="current-position" select="$current-position + 1"/>
        <xsl:with-param name="max" select="$max"/>
      </xsl:apply-templates>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="ax:items" mode="repeat">
    <xsl:param name="current-position" />

<!-- instead of using ax:item, you could just 'grab' and insert elements by position -->
<!-- Note that I use apply-templates here, so that a ax:repeat item could contain another ax:repeat item -->
<xsl:apply-templates select="*[position() = $current-position]" />
</xsl:template>


</xsl:stylesheet>

Cheers,
Geert

Current Thread