RE: [xsl] xsl:call-template question

Subject: RE: [xsl] xsl:call-template question
From: "Michael Kay" <mike@xxxxxxxxxxxx>
Date: Wed, 23 Aug 2006 19:28:16 +0100
I thought you had an answer to this before, perhaps you didn't understand
it, but that's no reason to ignore it.

It's difficult to tell exactly what's going on, because you haven't shown
the call of repeat-twice (what's the context node, and what are the supplied
parameters?), and you haven't shown the template named "calculate".

But whatever calculate does, it just writes its output to the result tree. I
think you might be imagining that it somehow modifies the values of start
and base the next time the repeat-twice template is called.

This kind of logic:

<xsl:for-each select="node()">
> 	  <xsl:choose>
> 	    <xsl:when test="local-name(.)='SCID'">

is a sort of hand-cranked call on xsl:apply-templates. Much better to use
the real thing.

Basically all you need to do is something like

<xsl:template match="stream_loop">
<stream_loop>
	<xsl:apply-templates select="stream_definition">
  		<xsl:with-param name="base" select="4112"/>
	</xsl:apply-templates>
	<xsl:apply-templates select="stream_definition">
  		<xsl:with-param name="base" select="4114"/>
	</xsl:apply-templates>
</stream_loop>
</xsl:template>

<xsl:template match="SCID">
  <xsl:param name="base">
       <PID><xsl:value-of select="$base"/></SCID>
       <ECM><xsl:value-of select="$base + 1"/></ECM>
</xsl:template>

<xsl:template match="*">
  <xsl:param name="base">
  <xsl:copy>
    <xsl:apply-templates select="*">
      <xsl:with-param name="base" select="$base"/>
    </xsl:apply-templates>
  </xsl:copy>
</xsl:template>

In XSLT 2.0 the complicated parameter passing can be greatly simplified
using tunnel parameters.

Michael Kay
http://www.saxonica.com/



> -----Original Message-----
> From: Lin, Jessica [mailto:jlin@xxxxxxxxxxx] 
> Sent: 23 August 2006 19:11
> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> Subject: [xsl] xsl:call-template question
> 
> Here is the block of xml file. I want to repeat stream twice 
> in stream_loop and change the SCID to PID with differenct 
> start number by using xsl:call-template.
> 
>   <stream_loop>
>     <stream_definition>
>       <stream_type>2</stream_type>
>       <SCID>100</SCID>
>       <descriptors_loop_length>compute</descriptors_loop_length>
>       <descriptor_loop>
>         <about_descriptor>some description</about_descriptor>
>         <additional_descriptor>other 
> description</additional_descriptor>
>       </descriptor_loop>
>     </stream_definition>
>   </stream_loop>
> 
> 
> Here is the expected result:
>  <stream_loop>
>     <stream>
>       <stream_type>2</stream_type>
>       <PID>4112</SCID>
>       <ECM>4113</ECM>
>       <descriptors_loop_length>compute</descriptors_loop_length>
>       <descriptor_loop>
>         <about_descriptor>some description</about_descriptor>
>         <additional_descriptor>other 
> description</additional_descriptor>
>       </descriptor_loop>
>     </stream>
>     <stream>
>       <stream_type>2</stream_type>
>       <PID>4114</SCID>
>       <ECM>4115</ECM>
>       <descriptors_loop_length>compute</descriptors_loop_length>
>       <descriptor_loop>
>         <about_descriptor>some description</about_descriptor>
>         <additional_descriptor>other 
> description</additional_descriptor>
>       </descriptor_loop>
>     </stream>
>   </stream_loop>
> 
> 
> 
> Here is my xslt block:
> 
> 
> <xsl:template name="repeat twice">		
>   <xsl:param name="base" select="4112"/>
>   <xsl:param name="start" select="0"/>
>   <xsl:choose>
>     <xsl:when test="$start &lt; 2">
>       <stream>
> 	<xsl:for-each select="node()">
> 	  <xsl:choose>
> 	    <xsl:when test="local-name(.)='SCID'">
> 	      <PID>
> 		    <xsl:value-of select="$base"/>
> 	      </PID>
>               <ECM>
>                 <xsl:value-of select="$base+1"/>
> 	      </ECM>					
> 	    </xsl:when>
> 	    <xsl:otherwise>
> 	      <xsl:copy-of select="."/>
> 	    </xsl:otherwise>
> 	  </xsl:choose>
> 	</xsl:for-each>
>       </stream>						
> 		
>       <xsl:call-template name="calculate">
> 	<xsl:with-param name="base" select="$base+$start*2" />
> 	<xsl:with-param name="start" select="$start+1"/>
>       </xsl:call-template>	
>     </xsl:when>	
>   </xsl:choose>
> </xsl:template>
> 
> 
> But the real result is not as what I am expecting. Can anyone 
> tell me what's wrong in my xslt block? Thank a lot.
> 
> 
> --- Jessica

Current Thread