<xsl:template name="body">
<xsl:call-template name="test1">
<xsl:with-param name="var1" >
<a>foo</a>
</xsl:with-param>
</xsl:call-template>
</xsl:template>
The $var1
parameter passed to the template is hardly usable in XSLT 1.0/XPath 1.0 due to the infamous RTF (Result-Tree Fragment) type.
From the W3C XSLT 1.0 spec.:
11.1 Result Tree Fragments
Variables introduce an additional data-type into
the expression language. This
additional data type is called result
tree fragment. A variable may be bound
to a result tree fragment instead of
one of the four basic XPath data-types
(string, number, boolean, node-set). A
result tree fragment represents a
fragment of the result tree. A result
tree fragment is treated equivalently
to a node-set that contains just a
single root node. However, the
operations permitted on a result tree
fragment are a subset of those
permitted on a node-set. An
operation is permitted on a result
tree fragment only if that operation
would be permitted on a string (the
operation on the string may involve
first converting the string to a
number or boolean). In particular, it
is not permitted to use the /
, //
,
and []
operators on result tree
fragments. When a permitted operation
is performed on a result tree
fragment, it is performed exactly as
it would be on the equivalent
node-set.
When a result tree fragment is copied
into the result tree (see [11.3 Using
Values of Variables and Parameters
with xsl:copy-of]), then all the nodes
that are children of the root node in
the equivalent node-set are added in
sequence to the result tree.
Expressions can only return values of
type result tree fragment by
referencing variables of type result
tree fragment or calling extension
functions that return a result tree
fragment or getting a system property
whose value is a result tree fragment.
To circumvent this crippling design decision, almost every XSLT processor has its own extension function, usually named xxx:node-set()
where the xxx
prefix must be bound to a vendor-defined namespace.
Solution:
Find exactly what is the name of this extension function offered by your XSLT processor vendor.
Or, if your XSLT processor supports EXSLT, use the exsl:node-set()
extension function as defined by EXSLT.
Here are some vendor-specific namespaces:
MSXML and .NET XslCompiledTransform, XslCompiledTransform:
xmlns:vendor="urn:schemas-microsoft-com:xslt"
Xalan (note, the function name is: xxx:nodeset()
!):
xmlns:vendor="http://xml.apache.org/xalan"
Saxon (6.x):
xmlns:vendor="http://icl.com/saxon"
All XSLT processors that implement EXSLT:
xmlns:vendor="http://exslt.org/common"
In case the body of the <xsl:param>
isn't dynamically constructed, one can avoid the
xxx:node-set()
function in the following way:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes"/>
<xsl:variable name="vrtfparamXML">
<a>
<b>foo</b>
</a>
</xsl:variable>
<xsl:variable name="vparamXML" select=
"document('')/*/xsl:variable
[@name='vrtfparamXML']/*"/>
<xsl:template match="/">
<xsl:copy-of select="$vparamXML/b"/>
</xsl:template>
</xsl:stylesheet>
when this transformation is applied on any XML document (not used), the result is the wanted child of the RTF:
<b xmlns:xsl="http://www.w3.org/1999/XSL/Transform">foo</b>
Note: XSLT 2.0/XPath 2.0 got rid of the RTF "type" and there one doesn't have any problem accessing temporary trees and navigating them using the full power of XPath 2.0