tags:

views:

50

answers:

3

Hello, I'm trying to find a solution for how to replace standard 3-line code of type "call-template" - "with-param" with one single line.

For example I have the following piece of code:

<xsl:call-template name="do_job">
    <xsl:with-param name="str">data1</xsl:with-param>
</xsl:call-template>

that i want to replace with something like this:

<myNs:tr name="data1"/>
A: 

It is not possible to create and use macros in XSLT.

In XSLT 2.0 one can write functions using the <xsl:function> instruction. Then a function is referenced in any XPath expression:

my:do_job(someString)

Here is a full example:

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema"
 xmlns:my="my:my">

 <xsl:template match="/">
  <xsl:sequence select="my:do_job('Hello, World!')"/>
 </xsl:template>

 <xsl:function name="my:do_job" as="xs:integer">
  <xsl:param name="pText" as="xs:string"/>

  <xsl:sequence select="string-length($pText)"/>
 </xsl:function>
</xsl:stylesheet>

when this transformation is applied on any XML document (not used), the correct result is produced:

13
Dimitre Novatchev
A: 

As Dimitre already said, macros are not supported. You could however generate your XSLT on the fly from an XML document containing macros and then run the generated XSLT.

A stylesheet that would create your XSLT would look like this:

<xsl:template match="myNs:tr">
    <xsl:call-template name="do_job">
        <xsl:with-param name="str" select="{@name}" />
    </xsl:call-template>
</xsl:template>
0xA3
A: 

Beside Dimitre excellent answer and recomendation, you could something like this stylesheet:

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:myNs="myNs"
exclude-result-prefixes="myNs">
    <myNs:tr name="data1"/>
    <myNs:tr name="data2"/>
    <xsl:template match="root">
        <root>
            <xsl:apply-templates/>
        </root>
    </xsl:template>
    <xsl:template match="data">
        <data>
            <macro>
                <xsl:apply-templates select="document('')/*/myNs:*
                                            [@name=current()]"/>
            </macro>
            <inline>
                <xsl:call-template name="do_job">
                    <xsl:with-param name="str" select="."/>
                </xsl:call-template>
            </inline>
        </data>
    </xsl:template>
    <xsl:template match="myNs:tr">
        <xsl:call-template name="do_job">
            <xsl:with-param name="str" select="@name"/>
        </xsl:call-template>
    </xsl:template>
    <xsl:template name="do_job">
        <xsl:param name="str"/>
        <xsl:value-of select="translate($str,'data','DATA')"/>
    </xsl:template>
</xsl:stylesheet>

With this input:

<root>
    <data>data1</data>
    <data>data2</data>
    <data>data3</data>
</root>

Output:

<root>
    <data>
        <macro>DATA1</macro>
        <inline>DATA1</inline>
    </data>
    <data>
        <macro>DATA2</macro>
        <inline>DATA2</inline>
    </data>
    <data>
        <macro></macro>
        <inline>DATA3</inline>
    </data>
</root>

Note: Also I recomend to you to read Dimitre Novatchev's FXSL in http://fxsl.sf.net/

Alejandro