What is the best way to loop in XSLT from 1 to 60? I research in net, there are some templates to do this, is there any other way for example like a built-in function?
You create an XSLT loop with the <xsl:for-each> tag. The value of the select attribute in this tag is an XPath expression that allows you to specify the data element to loop through. XPath expressions are constructed like file paths in an operating system, the forward slash (/) selects subdirectories.
Anyway, for a start, I would suggest to use <xsl:variable name="listData" select="met:getData($Id)"/> , that is all you can do on the XSLT side to bind the variable to the result from the function call, your current attempt makes the variable hold a tree fragment containing a text node with the string value of the ...
The XSLT 2.0 engine is backwards compatible. The only time the backwards compatibility of the XSLT 2.0 engine comes into effect is when using the XSLT 2.0 engine to process an XSLT 1.0 stylesheet.
This post shows you how to convert a simple XML file to CSV using XSLT. The following XSL Style Sheet (compatible with XSLT 1.0) can be used to transform the XML into CSV. It is quite generic and can easily be configured to handle different xml elements by changing the list of fields defined ar the beginning.
In XSLT 2.0,
<xsl:for-each select="1 to 60">...</xsl:for-each>
But I guess that you must be using XSLT 1.0, otherwise you wouldn't be asking.
In XSLT 1.0 you should use recursion: a template that calls itself with a counter that's incremented on each call, and the recursion terminates when the required value is reached.
Alternatively there's a workaround in XSLT 1.0: provided your source document contains at least 60 nodes, you can do
<xsl:for-each select="(//node())[60 >= position()]">...</xsl:for-each>
The problem with simple recursion when processing long sequences is that often the space for the call stack becomes insufficient and the processing ends due to stack overflow. This typically happens with sequence length >= 1000.
A general technique to avoid this (implementable with any XSLT processor, even if it doesn't recognize tail-recursion) is DVC (Divide and Conquer) style recursion.
Here is an example of a transformation that successfully prints the numbers from 1 to 1000000 (1M):
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="text"/> <xsl:template match="/"> <xsl:call-template name="displayNumbers"> <xsl:with-param name="pStart" select="1"/> <xsl:with-param name="pEnd" select="1000000"/> </xsl:call-template> </xsl:template> <xsl:template name="displayNumbers"> <xsl:param name="pStart"/> <xsl:param name="pEnd"/> <xsl:if test="not($pStart > $pEnd)"> <xsl:choose> <xsl:when test="$pStart = $pEnd"> <xsl:value-of select="$pStart"/> <xsl:text>
</xsl:text> </xsl:when> <xsl:otherwise> <xsl:variable name="vMid" select= "floor(($pStart + $pEnd) div 2)"/> <xsl:call-template name="displayNumbers"> <xsl:with-param name="pStart" select="$pStart"/> <xsl:with-param name="pEnd" select="$vMid"/> </xsl:call-template> <xsl:call-template name="displayNumbers"> <xsl:with-param name="pStart" select="$vMid+1"/> <xsl:with-param name="pEnd" select="$pEnd"/> </xsl:call-template> </xsl:otherwise> </xsl:choose> </xsl:if> </xsl:template> </xsl:stylesheet>
When applied on any XML document (not used) this transformation produces the wanted result -- all the numbers from 1 to 1000000.
You can use/adapt this transformation for any task that needs to "do something N times".
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