I want to do some calculation within the xslt file and need to do some squre root in the formula. can someone please point out if it is possible and how please?
Thanks a mill
I want to do some calculation within the xslt file and need to do some squre root in the formula. can someone please point out if it is possible and how please?
Thanks a mill
One can use the sqrt
template/function of FXSL:
I. In XSLT 1.0:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
<xsl:import href="sqrt.xsl"/>
<!-- To be applied on any source xml.
This also tests the within() function
-->
<xsl:output indent="yes" omit-xml-declaration="yes"/>
<xsl:template match="/">
sqrt(0.25):
<xsl:call-template name="sqrt">
<xsl:with-param name="N" select="0.25"/>
<xsl:with-param name="Eps" select="0.00001"/>
</xsl:call-template>
sqrt(1):
<xsl:call-template name="sqrt">
<xsl:with-param name="N" select="1"/>
<xsl:with-param name="Eps" select="0.00001"/>
</xsl:call-template>
sqrt(2):
<xsl:call-template name="sqrt">
<xsl:with-param name="N" select="2"/>
<xsl:with-param name="Eps" select="0.00001"/>
</xsl:call-template>
sqrt(9):
<xsl:call-template name="sqrt">
<xsl:with-param name="N" select="9"/>
<xsl:with-param name="Eps" select="0.00001"/>
</xsl:call-template>
sqrt(16):
<xsl:call-template name="sqrt">
<xsl:with-param name="N" select="16"/>
<xsl:with-param name="Eps" select="0.00001"/>
</xsl:call-template>
sqrt(25):
<xsl:call-template name="sqrt">
<xsl:with-param name="N" select="25"/>
<xsl:with-param name="Eps" select="0.00001"/>
</xsl:call-template>
sqrt(36):
<xsl:call-template name="sqrt">
<xsl:with-param name="N" select="36"/>
<xsl:with-param name="Eps" select="0.00001"/>
</xsl:call-template>
sqrt(49):
<xsl:call-template name="sqrt">
<xsl:with-param name="N" select="49"/>
<xsl:with-param name="Eps" select="0.00001"/>
</xsl:call-template>
sqrt(64):
<xsl:call-template name="sqrt">
<xsl:with-param name="N" select="64"/>
<xsl:with-param name="Eps" select="0.00001"/>
</xsl:call-template>
sqrt(81):
<xsl:call-template name="sqrt">
<xsl:with-param name="N" select="81"/>
<xsl:with-param name="Eps" select="0.00001"/>
</xsl:call-template>
sqrt(100):
<xsl:call-template name="sqrt">
<xsl:with-param name="N" select="100"/>
<xsl:with-param name="Eps" select="0.00001"/>
</xsl:call-template>
sqrt(121):
<xsl:call-template name="sqrt">
<xsl:with-param name="N" select="121"/>
<xsl:with-param name="Eps" select="0.00001"/>
</xsl:call-template>
</xsl:template>
</xsl:stylesheet>
When this transformation is applied on any XML document (not used), the wanted correct result is produced:
sqrt(0.25):
0.5000000795866174
sqrt(1):
1.0000000464611474
sqrt(2):
1.4142156862745097
sqrt(9):
3.0000000000393214
sqrt(16):
4.0000001858445895
sqrt(25):
5.000000000016778
sqrt(36):
6.000000002793968
sqrt(49):
7.000000094930961
sqrt(64):
8.000001273385879
sqrt(81):
9.000009415515176
sqrt(100):
10.000000000107445
sqrt(121):
11.000000001323027
II. Using FXSL 2.x for XSLT 2.0:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:f="http://fxsl.sf.net/">
<xsl:import href="../f/func-sqrt.xsl"/>
<xsl:import href="../f/func-map.xsl"/>
<xsl:import href="../f/func-standardXpathFunctions.xsl"/>
<xsl:output method="text"/>
<xsl:template match="/">
<xsl:value-of separator="
" select=
"f:map(f:round-half-to-even(f:sqrt(2, 0.000001)),
0 to 13
)
"/>
</xsl:template>
</xsl:stylesheet>
When this transformation is applied on any XML document (not used), the wanted, correct result is produced:
1
1.4
1.41
1.414
1.4142
1.41421
1.414214
1.4142136
1.41421356
1.414213562
1.4142135624
1.41421356237
1.414213562375
1.4142135623747
If you are using XSLT 2.0, then problem sorted -- See Dimitre's answer. If you are using XSLT 1.0, in practice in a production environment, I would still go with Dimitre's answer. Commercially, it is better to use a tested libary than re-invent the wheel.
However I thought your question might be fun to implement a stand-alone solution for. And it was!
Given this bunch of values to find the roots of...
<squares>
<square>0</square>
<square>0.25</square>
<square>1</square>
<square>9</square>
<square>10</square>
</squares>
...when input to this XSLT 1.0 style-sheet...
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:variable name="verysmall" select="0.00001" />
<xsl:template match="/">
<roots>
<xsl:apply-templates select="*/square"/>
</roots>
</xsl:template>
<xsl:template match="square">
<root>
<xsl:call-template name="root">
<xsl:with-param name="x" select="." />
</xsl:call-template>
</root>
</xsl:template>
<xsl:template name="root">
<xsl:param name="x"/><!-- Assume x >= 0 -->
<xsl:choose>
<xsl:when test="$x > 1">
<xsl:call-template name="iterate-root">
<xsl:with-param name="x" select="$x" />
<xsl:with-param name="H" select="$x" />
<xsl:with-param name="L" select="0" />
</xsl:call-template>
</xsl:when>
<xsl:when test="($x = 1) or ($x <= 0)">
<xsl:value-of select="$x" />
</xsl:when>
<xsl:otherwise>
<xsl:variable name="inv-root">
<xsl:call-template name="iterate-root">
<xsl:with-param name="x" select="1 div $x" />
<xsl:with-param name="H" select="1 div $x" />
<xsl:with-param name="L" select="0" />
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="1 div $inv-root" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="iterate-root">
<xsl:param name="x"/> <!-- Assume x > 1 -->
<xsl:param name="H"/> <!-- High estimate -->
<xsl:param name="L"/> <!-- Low estimate -->
<xsl:variable name="M" select="($H + $L) div 2" />
<xsl:variable name="g" select="($M * $M - $x) div $x" />
<xsl:choose>
<xsl:when test="(($g < $verysmall) and ((- $g) < $verysmall)) or
(($H - $L) < $verysmall)">
<xsl:value-of select="$M"/>
</xsl:when>
<xsl:when test="$g > 0">
<xsl:call-template name="iterate-root">
<xsl:with-param name="x" select="$x" />
<xsl:with-param name="H" select="$M" />
<xsl:with-param name="L" select="$L" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="iterate-root">
<xsl:with-param name="x" select="$x" />
<xsl:with-param name="H" select="$H" />
<xsl:with-param name="L" select="$M" />
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
...yields approximate solutions...
<roots>
<root>0</root>
<root>0.5</root>
<root>1</root>
<root>2.999988555908203</root>
<root>3.1622695922851562</root>
</roots>
The technique uses Divide-And-Conquer to find the root of the equation f(y) = y*y - x, which occurs at the square root of x. The technique is probably only reasonably efficient for XSLT processors which implement optimized tail-end recursion.