tags:

views:

52

answers:

3

Hello,

I have one template (which I cannot change but have to use), that processes the currently selected node, it might look like this (heavily simplified):

<xsl:template name="foreignTemplate">
    <xsl:value-of select="." />
</xsl:template>

In XSLT 2.0 I could do something like this to bind "." in that template to an arbitrary variable:

<xsl:template match="dummyNode">
    <xsl:variable name="inputString">foobar</xsl:variable>
    <xsl:variable name="result" select="$inputString">
        <xsl:call-template name="foreignTemplate" />
    </xsl:variable>
</xsl:template>

Given this source document:

<?xml version="1.0"?>
<dummyNode>DUMMY TEXT</dummyNode>

applying the above transformation with an XSLT 2.0 processor would evaluate to "foobar".

However, in XSLT 1.0 xsl:variable-Elements cannot have a select attribute and be non-empty at the same time. How can I achieve the same result in XSLT 1.0?

A: 

To apply the template to a constant string you can use a nodeset that is contained in your stylesheet and access it using the document function. With an empty string as parameter the result is the stylesheet document itself.

<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:foo="http://stackoverflow.com/questions/3423923/"&gt;
    <xsl:output method="xml" indent="yes" encoding="utf-8" />

    <foo:data>foobar</foo:data>

    <xsl:template name="foreignTemplate">
        <xsl:value-of select="." />
    </xsl:template>

    <xsl:template match="/">
        <xsl:for-each select="document('')/xsl:stylesheet/foo:data">
            <xsl:call-template name="foreignTemplate" />
        </xsl:for-each>
    </xsl:template>

</xsl:stylesheet>
Jörn Horstmann
A: 

in XSLT 1.0 xsl:variable-Elements cannot have a select attribute and be non-empty at the same time

First, the same holds for XSLT 2.0 (and for every instruction that have a @select and allow a sequence constructor in XSLT 2.0)

Second, if you want to change the context node (or context item in XSLT 2.0) before you call a name template, you should do:

<xsl:for-each select="$here-the-context-you-want"> 
    <xsl:call-template name="foreignTemplate" /> 
</xsl:for-each> 
Alejandro
+1  A: 

In XSLT 2.0 I could do something like this to bind "." in that template to an arbitrary variable:

<xsl:template match="dummyNode"> 
    <xsl:variable name="inputString">foobar</xsl:variable>

    <xsl:variable name="result" select="$inputString"> 
        <xsl:call-template name="foreignTemplate" /> 
    </xsl:variable> 
</xsl:template>

This is not true.

Both in XSLT 1.0 and 2.0 an <xsl:variable> csn have either a select attribute or a body (sequence constructor), but having both at the same time is an error.

From the XSLT 2.0 spec: "[ERR XTSE0620] It is a static error if a variable-binding element has a select attribute and has non-empty content."

I would recommend the following writing style:

In XSLT 1.0:

Do not rely on the context node as an implicit parameter. Use explicit parameters:

<xsl:template name="foreignTemplate">  
  <xsl:param name="pElement"     
  <xsl:value-of select="$pElement" />       
</xsl:template>

and in another template call it like this:

<xsl:call-template name="foreignTemplate">
 <xsl:with=param name="pElement" select="someExpression"/>
</xsl:call-template>

In XSLT 2.0: Use <xsl:function> instead of <xsl:template> :

<xsl:function name="my:foo" as="xs:string">
  <xsl:param name="pElement" as="element()"/>

  <xsl:sequence select="string($pElement)"/>
</xsl:function>

and call it like this as part of any XPath expression:

  my:foo(someElement)
Dimitre Novatchev
@Dimitre: +1 for detailed explanation! But, I think you've been too emphatic in rejecting the context node as implicit parameter. Several times is what we do, for example, when we call the identity transformation template.
Alejandro
@Alejandro: Thanks, and you're right about the implicit parameter, however I wouldn't recommend this to XSLT novices, because an inadvertent mistake could add too much in their overall confusion with (the new to them area of) XSLT. :)
Dimitre Novatchev
thank you! I'm not happy with this either, but as I wrote, I didn't write that template, nor can I change it... :)
hannes