tags:

views:

280

answers:

3

I don't know if it's possible, but I'm wondering how to do it...

Let's say we have the following XSL:

<xsl:template name="foo">
  Bla bla bla
</xsl:template>
...
<xsl:template name="bar">
  Bla bla bla
</xsl:template>
...
<xsl:template match="/">
  <xsl:if test="$templateName='foo'">
    <xsl:call-template name="foo"/>
  </xsl:if>
  <xsl:if test="$templateName='bar'">
    <xsl:call-template name="bar"/>
  </xsl:if>
</xsl:template>

Is it possible to change the XSL to read something like...

<xsl:template match="/">
  <xsl:call-template name="$templateName"/>
</xsl:template>
+1  A: 

No, this is not possible not directly possible. The calling convention is:

<xsl:call-template name="QName" />

Where a QName is defined as:

QName ::= PrefixedName | UnprefixedName

PrefixedName   ::= Prefix ':' LocalPart
UnprefixedName ::= LocalPart

Prefix         ::= NCName
LocalPart      ::= NCName

Basically this boils down to "characters only, no expressions". As the other answers highlight, there are in fact ways to do something equivalent, but the straightforward approach/naïve approach will not work.

Tomalak
Ah, but there is an ugly hack to work around this - see my answer.
Pavel Minaev
@Tomalak This has been possible (although in a different syntactic form) for almost 8 years :) See my answer for details.
Dimitre Novatchev
+2  A: 

It's not possible exactly as you describe, but if you want to be able to choose a template at run-time based on some value you set elsewhere, there is a trick to do that. The idea is to have your named template also match a node with a corresponding name in a distinct mode (so that it doesn't mess up your normal transformation), and then match on that. For example:

<xsl:stylesheet ... xmlns:t="urn:templates">

  <!-- Any compliant XSLT processor must allow and ignore any elements 
       not from XSLT namespace that are immediate children of root element -->
  <t:templates>
    <t:foo/>
    <t:bar/>
  </t:templates>

  <!-- document('') is the executing XSLT stylesheet -->     
  <xsl:variable name="templates" select="document('')//t:templates" />

  <xsl:template name="foo" match="t:foo" mode="call-template">
    Bla bla bla
  </xsl:template>

  <xsl:template name="bar" match="t:foo" mode="call-template">
    Bla bla bla
  </xsl:template>

  <xsl:template match="/">
    <xsl:variable name="template-name" select="..." />
    <xsl:apply-templates select="$templates/t:*[local-name() = $template-name]"
                         mode="call-template"/>
  </xsl:template>

Note that you can use <xsl:with-param> in <xsl:apply-templates>, so you can do everything with this that you could do with a plain <xsl:call-template>.

Also, the code above is somewhat lengthier than you might need because it tries to avoid using any XSLT extensions. If your processor supports exslt:node-set(), then you can just generate nodes directly using <xsl:element>, and use node-set() to convert the resulting tree fragment to a plain node to match against, without the need for document('') hack.

For more information, see FXSL - it's a functional programming library for XSLT that is based on this concept.

Pavel Minaev
+1  A: 

Update: The links below were updated to point to web.archive.org -- unfortunately, IDEALLIANCE has made all Exteme Markup Languages conference proceedings unavailable... In due time, I will find a more permanent place for these two articles.


This is implemented in FXSL.

There are good explanations of the main principles of FXSL.

See the following two articles:

"Functional programming in XSLT using the FXSL library" (for XSLT 1.0), (PDF) at:

http://web.archive.org/web/20070710091236/http://www.idealliance.org/papers/extreme/proceedings/xslfo-pdf/2003/Novatchev01/EML2003Novatchev01.pdf

(HTML) at:

http://conferences.idealliance.org/extreme/html/2003/Novatchev01/EML2003Novatchev01.html



"Higher-Order Functional Programming with XSLT 2.0 and FXSL" (PDF) at:

http://web.archive.org/web/20070222111927/http://www.idealliance.org/papers/extreme/proceedings/xslfo-pdf/2006/Novatchev01/EML2006Novatchev01.pdf

(HTML) at: http://conferences.idealliance.org/extreme/html/2006/Novatchev01/EML2006Novatchev01.html



Using FXSL I have been able to solve easily and elegantly many problems, that seem "impossible for XSLT". One can find a lot of examples here.

Dimitre Novatchev
Welcome back. :)
Tomalak
Unfortunately, both of your links don't work, can you re-check them? Maybe they are bound to a valid session or something, I keep getting "Page Not Found" errors.
Tomalak
@Tomalak: Thank you for letting me know. I will investigate. There is something strange this morning: facebook is unaccessible and twitter seems hacked ...
Dimitre Novatchev
Yes, Twitter is down for me, too. Luckily I have no Facebook account, that's one less addiction. ;-)
Tomalak
@Tomalak: Sorry, I cannot make the links appear as they should. Do you know any workaround? Thanks!
Dimitre Novatchev