Grim
Grim

Reputation: 2040

Custom XSLT Tag

I am sick of write all the call-template/with-param stuff.

Is there any shortcut for this in example:

<xsl:call-template name="complexwidget">
     <xsl:with-param name="a" select="$bla_213"/>
     <xsl:with-param name="b" select="$bla_213"/>
     <xsl:with-param name="c" select="$bla_213"/>
     <xsl:with-param name="d" select="$bla_213"/>
</xsl:call-template>

A Perfect posibility would be this:

<complex a="{$bla_213}" b="{$bla_213}" c="{$bla_213}" d="{$bla_213}" />

Any idea, maybe a twice-transform-xslt??

Upvotes: 0

Views: 452

Answers (1)

Jirka Š.
Jirka Š.

Reputation: 3428

If you could switch to xslt 2.0 then user functions would be exactly what you need.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:my="my-namespace">
    <xsl:output method="text" version="1.0" encoding="UTF-8" indent="yes"/>

    <xsl:template match="/">
        <xsl:value-of select="my:complexWidget(1, 2, 3, 4)" />
    </xsl:template>

    <xsl:function name="my:complexWidget">
        <xsl:param name="a" />
        <xsl:param name="b" />
        <xsl:param name="c" />
        <xsl:param name="d" />
        <!-- Do something -->
        <xsl:value-of select="($a, $b,$c, $d)" separator="-" />
    </xsl:function>

</xsl:stylesheet>

In xslt 1.0 I think that preprocessing of xslt stylesheet with another transformation will be the only way (or may be writing some extension functions in language of your processor .

EDIT:

I tried the "preprocess" of xslt and it seems to be working (but probably it is no the most elegant way how to do it).

Input xslt

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:mypp="my-preprocess-namespace">
    <xsl:output method="text" />

    <xsl:template match="/">
        <xsl:variable name="varA" select="1"/>
        <xsl:variable name="varB" select="2"/>
        <xsl:variable name="varC" select="3"/>
        <xsl:variable name="varD" select="4"/>
        <mypp:complexWidget a="$varA" b="$varB" c="$varC" d="$varD"/>
    </xsl:template>

    <xsl:template name="complexWidget">
        <xsl:param name="a"/>
        <xsl:param name="b"/>
        <xsl:param name="c"/>
        <xsl:param name="d"/>
        <!-- do something-->
        <xsl:value-of select="$a"/>
        <xsl:text>-</xsl:text>
        <xsl:value-of select="$b"/>
        <xsl:text>-</xsl:text>
        <xsl:value-of select="$c"/>
        <xsl:text>-</xsl:text>
        <xsl:value-of select="$d"/>
    </xsl:template>
</xsl:stylesheet>

I defined here a special namespace for element to be replaced (i.e. xmlns:mypp="my-preprocess-namespace"). Element to be replaced is <mypp:complexWidget a="$varA" b="$varB" c="$varC" d="$varD"/>.

This xslt I preprocess with following xslt.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:mypp="my-preprocess-namespace">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>


    <xsl:template match="node() | @*">
        <xsl:copy>
            <xsl:apply-templates select="node() | @*" />
        </xsl:copy>
    </xsl:template>

    <xsl:template match="mypp:*">
        <xsl:element name="xsl:call-template">
            <xsl:attribute name="name">
                <xsl:value-of select="local-name()" />
            </xsl:attribute>
            <xsl:for-each select="@*">
                <xsl:element name="xsl:with-param">
                    <xsl:attribute name="name">
                        <xsl:value-of select="name()" />
                    </xsl:attribute>
                    <xsl:attribute name="select">
                        <xsl:value-of select="." />
                    </xsl:attribute>
                </xsl:element>
            </xsl:for-each>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

It is based on "Identity transform" - copy everything to the output just elements from special namespace transform into the call-template element. I guess this could be done in more nice way than I did.

The output is

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:mypp="my-preprocess-namespace" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="text" />

    <xsl:template match="/">
        <xsl:variable name="varA" select="1"/>
        <xsl:variable name="varB" select="2"/>
        <xsl:variable name="varC" select="3"/>
        <xsl:variable name="varD" select="4"/>
        <xsl:call-template name="complexWidget">
            <xsl:with-param name="a" select="$varA"/>
            <xsl:with-param name="b" select="$varB"/>
            <xsl:with-param name="c" select="$varC"/>
            <xsl:with-param name="d" select="$varD"/>
        </xsl:call-template>
    </xsl:template>

    <xsl:template name="complexWidget">
        <xsl:param name="a"/>
        <xsl:param name="b"/>
        <xsl:param name="c"/>
        <xsl:param name="d"/>
        <!-- do something-->
        <xsl:value-of select="$a"/>
        <xsl:text>-</xsl:text>
        <xsl:value-of select="$b"/>
        <xsl:text>-</xsl:text>
        <xsl:value-of select="$c"/>
        <xsl:text>-</xsl:text>
        <xsl:value-of select="$d"/>
    </xsl:template>

</xsl:stylesheet>

When I run the output as xslt stylesheet it produces expected output.

But I don't have any deeper experience with producing xslt stylesheet by another xslt so I don't know much about possible troubles with this approach.

Upvotes: 1

Related Questions