tags:

views:

549

answers:

3

Is it possible to pass a variable from one parent template to its child element ?

<xsl:template match="structure">
  <xsl:variable name="var"><xsl:value-of select="@path" /></xsl:variable>
  <xsl:apply-templates select="folders">
    <xsl:with-param name="var1" select="'{var}'"/>
  </xsl:apply-templates>
</xsl:template> 

this template will match:

<xsl:template match="folder">
  <xsl:param name="var1"/>
  <xsl:value-of select="$var1"/>
</xsl:template>

You see I wanna use var as var1 in the matched template.

How can I make this work?

edit: the structure is like this:

<structure path="C:\xampplite\htdocs\xampp">
  <folders>
    <folder name="img">
      <date>01/28/10 21:59:00</date>
      <size>37.4 KB</size>
    </folder>
 </folders>
</structure>

edit2:

<xsl:template match="folder">
<xsl:variable name="var1"><xsl:value-of select="../../@path"/></xsl:variable>
<xsl:variable name="var2"><xsl:value-of select="@name" /></xsl:variable>
<xsl:variable name="var3"><xsl:value-of select="$var1"/>\<xsl:copy-of select="$var2"/>    </xsl:variable>
 <th colspan="2" align="left"  bgcolor="#FF5500"><a onclick="foo('{$var3}')"><xsl:value-of select="$var3"/></a></th>

in the jscript function the string is without its backslashes. anyone knows why?

C:xampplitehtdocsxamppimg

+2  A: 

Two problems with the structure template:

  1. You are applying templates selecting folders, but have a template matching on folder. Either change it to folder, or if you have a folders template make sure that it passes the var1 parameter value down to the folder template.
  2. Your with-param @select uses '{var}', which selects that literal string {var}. If you want to select the var variable, then remove the surrounding quotes and curly braces and just select $var.

Applied changes to your structure template:

<xsl:template match="structure">
  <xsl:variable name="var"><xsl:value-of select="@path" /></xsl:variable>
  <xsl:apply-templates select="folder">
    <xsl:with-param name="var1" select="$var"/>
  </xsl:apply-templates>
</xsl:template>
Mads Hansen
+2  A: 

The exact code for the call would be:

<xsl:template match="structure">
  <xsl:variable name="var"><xsl:value-of select="@path" /></xsl:variable>
  <xsl:apply-templates select="folders/folder">
    <xsl:with-param name="var1" select="$var"/>
  </xsl:apply-templates>
</xsl:template>

Another way to access the @path attribute of the root node would be modifying your template to:

<xsl:template match="folder">
  <xsl:value-of select="../../../@path"/>
</xsl:template>
sw
the last proposal works fine for me. thx
wanderameise
+3  A: 

You can pass parameters to named templates that you call via <xsl:call-template>, e.g.:

<xsl:call-template name="name">
   <xsl:with-param name="param" select="xpathexpr"/>
</xsl:call-template>

<xsl:template name="name">
   <xsl:param name="param"/>
   ...
</xsl:template>

When you call a named template, the context node is the current context. So to call a named template for child nodes, you need to change the current context by using <xsl:for-each>:

<xsl:for-each select="child">
   <xsl:call-template name="name">
      <xsl:with-param name="param" select="xpathexpr"/>
   </xsl:call-template>
</xsl:for-each>

In your case, though, there's no need to pass parameters, since the variable that you're trying to use is something that's navigable to from the context node. And you don't need to use all those variables (nor should you ever give a variable a name as useless as var1):

<xsl:template match="folder">
   <xsl:variable name="linkarg" value="concat(../../@path, '\\', @name)"/>
   <xsl:variable name="linktext" value="concat(../../@path, '\', @name)"/>
   <th colspan="2" align="left"  bgcolor="#FF5500">
      <a onclick="foo('{$linkarg}')">
         <xsl:value-of select="$linktext"/>
      </a>
   </th>
</xsl:template>

Also, I'd be tempted to use ancestor::structure[1]/@path rather than ../../@path, because it makes the intention a lot more explicit; your version means "get the path attribute from the parent of the parent element", while my version means "traverse up the chain of ancestor elements until you find the first one named structure, and get its path attribute."

Robert Rossney
+1 for advising the idiomatic way of doing it (e.g. using context instead of variables). (BTW: The backslashes in your answer need to be fixed.)
Tomalak
Oh, right. JavaScript. Fixed.
Robert Rossney
@Robert Rossney: No, still not completely fixed. No backslashes allowed in XPath (see last paragraph).
Tomalak
Whoops. I strive to test all code I post to SO, because of stupid mistakes like that. But I don't know how to test my *sentences*. Fixed, thanks.
Robert Rossney