Re: [xsl] loop without switching context

Subject: Re: [xsl] loop without switching context
From: David Carlisle <davidc@xxxxxxxxx>
Date: Thu, 22 Mar 2012 23:44:51 +0000
On 22/03/2012 23:36, Fred Christian wrote:
I ran into a challenge today that I ended up working around.
I wonder though if there is a direct solution.

Is there a way to write a loop without switching context?
I am using XSLT 2.0 and Saxon.

If I loop through a set of values using<xsl:for-each>  then my context
is set to the xml that contains that data. But I want my context to be
set to the xml before I entered the for-each.

Some example code.
I had this.
<xsl:call-template name="a"><xsl:with-param
name="x">01</xsl:with-param></xsl:call-templates>
<xsl:call-template name="a"><xsl:with-param
name="x">02</xsl:with-param></xsl:call-templates>
{duplicated about 10 times}

It works okay, but it is hard-coded (bad).
I will have cases where my list of x values will vary, but they will
always be short strings like {01,02,A1,B3}. And the number of values
will always be less than 20.

So I thought of using xsl:for-each on a data file for the x values.
Like this
<xsl:variable name="datafile">../data.xml</xsl:variable>

It's much better to use <xsl:variable name="datafile" select="'../data.xml'"/>
<xsl:for-each select="document($datafile)/data/xvals/x">
   <xsl:call-template name="a"><xsl:with-param
name="x">01</xsl:with-param></xsl:call-templates>
</xsl:for-each>

The loop works, but it switches my context so that template "a" no
longer has the xml it needs.
I realized I could pass in the context node as a param, but it seems
that is only giving me access to children and not ancestors of the
context node.

No if you pass a param (make sure you use the select attribute) then you have a reference to the node in the original document and can traverse up or down.


I suspect that you went
<xsl:with-param name="x">
<xsl:copy-of select="."/>
</xsl:with-param>
That creates a copy of the node (and its descendants but not its ancestors) so it is inefficient and not what you want, if you go
<xsl:with-param name="x" select="."/>
then you pass the node not a copy and so it has its ancestors intact.



Maybe I have hit a case where I am just modeling the project wrong and need to rethink it some. Or, is there a way to write a loop without switching context?

Thanks,
Fred


David


Current Thread