I have work out the example for factorial of given number in xml by using xsl.
My XML code is,fact.xml
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="fact.xsl"?>
<numbers>
<number> 5
</number>
</numbers>
and my XSL code is,fact.xsl
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:apply-templates>
</xsl:apply-templates>
</xsl:template>
<xsl:template name="factorial">
<xsl:param name="number" select="$number"/>
<xsl:param name="result" select="1"/>
<xsl:if test="$number > 1">
<xsl:call-template name="factorial">
<xsl:with-param name="number" select="$number - 1"/>
<xsl:with-param name="result">
<xsl:value-of select="$number * $result"/>
</xsl:with-param>
</xsl:call-template>
</xsl:if>
<xsl:if test="$number = 1">
<xsl:value-of select= "$result"/>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
But, When I run this fact.xml, the factorial output shows only 5 instead of 120.
So what is the error in the code, either in XML or XSL?
Thanks in advance.
Your first template matches
numbersnode, but does nothing.Your second template doesn’t match anything, and is never called by any other template. In other words, it is never executed.
That’s why the output is 5.
Let’s see what happens. In XSLT, templates can be called in two ways.
/numbersnode; in your revision, it matches any root element (which is, in this case, the same thing).call-template. That’s what you are doing in your second template, calling itself recursively.The problem is that the second template is called only from… guess… the second template itself. So since it’s never called, it will never execute.
Now, we will add a call to this template from the outside, and more precisely from the first template.
We also want to be sure that the template is executing properly, so we output the intermediary states.
The final result is correct, but the first intermediary state is still weird. It shows that the number
5was treated as a string, with leading and trailing whitespace.To get rid of that, the
numberelement innerXML must be converted to a real number. To do that, you can use thenumber()method:Now, the output is correct from the start to the end, and intermediary output can be removed.