I am using a recursive template that searches for some specific elements like this:
<xsl:template name="GetProdDependency">
<xsl:param name="TechProd"></xsl:param>
<xsl:param name="BeatenPath"></xsl:param>
<xsl:variable name="TechProdArch" select="$TechProd/pro:own_slot_value[pro:slot_reference='technology_product_architecture']/pro:value"></xsl:variable>
<xsl:variable name="TechProdArchNode" select="/node()/pro:simple_instance[pro:name=$TechProdArch]"></xsl:variable>
<xsl:variable name="TechProdCompList" select="$TechProdArchNode/pro:own_slot_value[pro:slot_reference='contained_techProd_components']/pro:value"/>
<xsl:for-each select="$TechProdCompList">
<xsl:variable name="TechProdAsRole" select="/node()/pro:simple_instance[pro:name=current()]/pro:own_slot_value[pro:slot_reference='technology_product_as_role']/pro:value"/>
<xsl:variable name="TechProdRole" select="/node()/pro:simple_instance[pro:name=$TechProdAsRole]/pro:own_slot_value[pro:slot_reference='role_for_technology_provider']/pro:value"/>
<xsl:variable name="DepTechProd" select="/node()/pro:simple_instance[pro:name=$TechProdRole]"/>
<!-- Check for beaten Path -->
<!-- if $DepTechProd/pro:own_slot_value[pro:slot_reference='name']/pro:value in BeatenPath -->
<xsl:if test="not($BeatenPath[string(.)=string($DepTechProd/pro:own_slot_value[pro:slot_reference='name']/pro:value)])">
<!-- Do the recursion here! -->
<!--<xsl:value-of select="$DepTechProd/pro:own_slot_value[pro:slot_reference='name']/pro:value"/> (type: <xsl:value-of select="$DepTechProd/pro:type"/> and Class: <xsl:value-of select="$DepTechProd/pro:name"/>)-->
<!--<xsl:value-of select="$DepTechProd/pro:own_slot_value[pro:slot_reference='name']/pro:value"/>-->
<xsl:value-of select="$DepTechProd"/>
<xsl:call-template name="GetProdDependency">
<xsl:with-param name="TechProd" select="$DepTechProd"></xsl:with-param>
<xsl:with-param name="BeatenPath" select="$TechProd|$DepTechProd/pro:own_slot_value[pro:slot_reference='name']/pro:value"></xsl:with-param>
<xsl:with-param name="Rev" select="$Rev + 1"></xsl:with-param>
</xsl:call-template>
</xsl:if>
</xsl:for-each>
</xsl:template>
This is working fine in the searching etc.
But when I get the result in the original caller, I was expecting to get a list of nodes from the calling.
I call it like:
<xsl:variable name="DelPlist">
<xsl:call-template name="GetProdDependency">
<xsl:with-param name="TechProd" select="$TechProd"></xsl:with-param>
<xsl:with-param name="BeatenPath" select="$TechProd/pro:own_slot_value[pro:slot_reference='name']/pro:value"></xsl:with-param>
<xsl:with-param name="Rev" select="1"></xsl:with-param>
</xsl:call-template>
</xsl:variable>
And I was expecting to get a list of nodes that I can iterate through with <xsl:for-each>
. But If I check for the count($DelPlist)
, I get 1 as result and I can not iterate.
Can somebody help?
The answer to your question is: in XSLT 2.0 yes, in XSLT 1.0 no.
In XSLT 2.0 both templates and functions can return any value. The type of the result can be specified using the as attribute (for example as="node()*"), and you can use the xsl:sequence instruction to set the result to be the result of any XPath expression.
In XSLT 1.0, if you capture the result of xsl:call-template in a variable, the value of the variable will always be a result tree fragment.
You must specify the type of the result of the template in its as
attribute.
If unspecified, the type is document-node()
and then in order to iterate through the result, you need to get the children of the result.
Solution: Specify the return type of the template with an as
attribute.
Here is a complete example:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/">
<xsl:variable name="vNodes" as="element()*">
<xsl:call-template name="genNodes"/>
</xsl:variable>
<xsl:for-each select="$vNodes">
<xsl:value-of select="concat('
', position(), ': ')"/>
<xsl:copy-of select="."/>
</xsl:for-each>
</xsl:template>
<xsl:template name="genNodes" as="element()*">
<a/>
<b/>
<c/>
</xsl:template>
</xsl:stylesheet>
when this transformation is applied on any XML document (not used), the wanted, correct result is produced:
1: <a/>
2: <b/>
3: <c/>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With