xslt 2.0 に切り替えることができれば、ユーザー関数はまさに必要なものになります。
<?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>
xslt 1.0 では、別の変換を使用して xslt スタイルシートを前処理することが唯一の方法になると思います (または、プロセッサの言語でいくつかの拡張関数を記述している可能性があります。
編集:
私は xslt の「前処理」を試してみましたが、うまくいっているようです (しかし、おそらくそれは最も洗練された方法ではありません)。
入力 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>
ここでは、要素を置き換えるための特別な名前空間 (つまりxmlns:mypp="my-preprocess-namespace"
) を定義しました。置換する要素は です<mypp:complexWidget a="$varA" b="$varB" c="$varC" d="$varD"/>
。
この xslt 次の 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>
これは「Identity 変換」に基づいています。特別な名前空間変換から call-template 要素への要素だけを出力にすべてコピーします。これは私がやったよりももっといい方法でできると思います。
出力は
<?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>
出力を xslt スタイルシートとして実行すると、期待どおりの出力が生成されます。
しかし、私は別の xslt で xslt スタイルシートを作成した経験があまりないため、このアプローチで起こりうる問題についてはあまり知りません。