Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't I get parameters to work with apply-templates in XSL?

I am finding it impossible to get with-param to work with apply-templates. As an example, I've hacked the examples given in w3schools.

xsl

<xsl:template match="/">
  <xsl:apply-templates>
    <xsl:with-param name="test" select="'has this parameter been passed?'"/>
  </xsl:apply-templates>
</xsl:template>

<xsl:template match="cd">
  <xsl:param name="test"></xsl:param>
  parameter:
  <xsl:value-of select="$test"></xsl:value-of>
</xsl:template>

xml

<catalog>
  <cd>
    <title>Empire Burlesque</title>
    <artist>Bob Dylan</artist>
    <country>USA</country>
    <company>Columbia</company>
    <price>10.90</price>
    <year>1985</year>
  </cd>
  <cd>
    <title>Hide your heart</title>
    <artist>Bonnie Tyler</artist>
    <country>UK</country>
    <company>CBS Records</company>
    <price>9.90</price>
    <year>1988</year>
  </cd>
</catalog>

(Hopefully) you'll see that the test parameter is not being passed to the cd template. I can get it to work when using call-template, but not apply-templates. What's going on? I am using XSL 1.0. Please ignore the fact that I'm passing a hard-coded parameter - this is just an example.

like image 487
darasd Avatar asked Feb 26 '09 11:02

darasd


3 Answers

Hmmm... interesting... fails for me using XslTransform and XslCompiledTransform in .NET - but it looks like it should work... curious...

update the problem seesm to be the root match; try

<xsl:template match="/catalog"> <!-- CHANGE HERE --> 
  <xsl:apply-templates>
    <xsl:with-param name="test" select="'has this parameter been passed?'"/>
  </xsl:apply-templates>
</xsl:template>

This then works for me without any other changes. The difference is that you were matching the root node. When you did your "apply templates", it cascaded first to catalog (with the param), then to cd (without the param). To get what you want, you need to start at catalog. You can see this by adding an <xsl:vaue-of select="name()"/> to the match, and then try it as "/" and "/catalog".

like image 82
Marc Gravell Avatar answered Nov 15 '22 10:11

Marc Gravell


Try specifying templates to apply:

<xsl:template match="/">
  <xsl:apply-templates select="catalog/cd">
    <xsl:with-param name="test" select="'has this parameter been passed?'"/>
  </xsl:apply-templates>
</xsl:template>
like image 21
Goran Avatar answered Nov 15 '22 09:11

Goran


you could always go with xsl:call-template.. eg:

...
<xsl:call-template name="foo">
   <xsl:with-param name="bars" select="42"/>
</xsl:call-template>
...

<xsl:template name="foo">
   <xsl:param name="bars"/>
   <xsl:value-of select="$node"/>
</xsl:template>
like image 28
Quinn Carver Avatar answered Nov 15 '22 09:11

Quinn Carver