views:

743

answers:

4

Hello. 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.

+1  A: 

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>
Goran
didn't catch that - try this solution. It seems something goes awry when not specifying the templates path.
Goran
yes, you are right. Howver, I believe that having // in the select is bad form. Furthermore, It seems that this double slash is crutial to passing parameters. In my real code, I was already passing a node in the select, however, the parameter was only passed after prefixing the node with //. WHY?
darasd
Ok - now SO is behaving strange - this question does not have 4 answers also your edits get shown and then get lost randomly...
Goran
I removed my original comment, as it no longer applied after you edited your answer!
darasd
Use Marc Gravell solution - I'm not sure why it should make a difference though - apply templates should work in all cases. Specifying catalog/cd instead of //cd works for me as well.
Goran
Sorry Goran; I thought I had it cracked, but I was wrong, so I rolled back an update. My bad - sorry for any confusion. And it does have 4 answers... if you have 10k+ rep ;-p (one is deleted)
Marc Gravell
I meant Marc Gravell answer was changing on every refresh... seems ok now
Goran
ah ok - will start deleting my comments soon :)
Goran
A: 

Works for me with libxslt 1.1.24 from http://xmlsoft.org/XSLT/ :

$ xsltproc xml1.xsl xml1.xml
<?xml version="1.0"?>


  parameter:
  has this parameter been passed?

  parameter:
  has this parameter been passed?
vartec
interesting. I am using MSXML 4.0. However, it also fails to work when I view it in Firefox.
darasd
Yeah, fails with Fx, works with Opera 10.
vartec
+2  A: 

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".

Marc Gravell
yes - that works but why doesn't the original example work!?
Goran
Ahh. But why doesn't the parameter get passed to cd?
darasd
catalog is the root here, so the original example should work. And it does with libXSLT and Opera.
vartec
"should" and "does"... don't always agree with each-other ;-p
Marc Gravell
@darasd - re the "why": because the default match is simply something like <apply-templates select="*"/>
Marc Gravell
A: 

I see the problem is that there is no match for cd element under root. Under root you have catalog element not a cd element, so modify the template to match='catalog'

indoraq