Hack 52 Perform Math with XSLT

figs/moderate.gif figs/hack52.gif

XPath 1.0 offers a number of math operations that can be performed within expressions.

With the help of XPath, XSLT can perform a number of math operations within expressions. Expressions can occur within the value of a select attribute. You can perform addition, subtraction, multiplication, division, and modulo operations. There are also a number of XPath functions that perform math, such as count(), ceiling(), floor(), number( ), round(), and sum().

Consider the following XML representation of a spreadsheet, worksheet.xml, with numbers arranged in columns and rows (Example 3-42).

Example 3-42. worksheet.xml
<?xml version="1.0" encoding="UTF-8"?>






















Using simple addition, the stylesheet sums.xsl (Example 3-43) sums the values in worksheet.xml first by rows, then by columns.

Example 3-43. sums.xsl
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output method="xml" encoding="UTF-8" indent="yes"/>


<xsl:template match="worksheet">




 <xsl:value-of select="column[1]/row[1] + column[2]/row[1] + column[3]/row[1]"/>



 <xsl:value-of select="column[1]/row[2] + column[2]/row[2] + column[3]/row[2]"/>



 <xsl:value-of select="column[1]/row[3] + column[2]/row[3] + column[3]/row[3]"/>



 <xsl:value-of select="column[1]/row[4] + column[2]/row[4] + column[3]/row[4]"/>





 <xsl:value-of select="column[1]/row[1] + column[1]/row[2] + column[1]/row[3] + 




 <xsl:value-of select="column[2]/row[1] + column[2]/row[2] + column[2]/row[3] + 




 <xsl:value-of select="column[3]/row[1] + column[3]/row[2] + column[3]/row[3] + 








Apply this stylesheet to worksheet.xml, directing the output to a file:

xalan -i 1 -o sum.xml worksheet.xml sums.xsl

sum.xml will look just like this:

<?xml version="1.0" encoding="UTF-8"?>














Now take another step by applying this little stylesheet, sum.xsl, to the output of the previous stylesheet. It uses the sum() function to check the sums of the rows and columns (Example 3-44).

Example 3-44. sum.xsl
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output method="text"/>


<xsl:template match="sums">

<xsl:value-of select="sum(sum[1]/*)"/> rows total

<xsl:value-of select="sum(sum[2]/*)"/> columns total


<xsl:value-of select="sum(sum/*)"/> rows + columns total

[<xsl:value-of select="sum(sum/*) div 2"/> divide by 2 check]




This is the command to transform it:

xalan sum.xml sum.xsl

Here is the output:

3660 rows total

3660 columns total


7320 rows + columns total

[3660 divide by 2 check]

XSLT 1.0 itself doesn't have much math capability, but if you want to do more, explore XSLT 2.0 or EXSLT's math extensions (http://www.exslt.org/math/index.html), described in [Hack #58] .