Math and XSLT
Math and XSLT

Math and XSLT

by Bob DuCharme
July 05, 2001

A Russian translation of this article can be found here.

XSLT's full support of XPath's math capabilities lets you do all the basic kinds of arithmetic and a little more. Let's look at a stylesheet that demonstrates these capabilities by using the values from this document:

<numbers>

<x>4</x>

<y>3.2</y>

<z>11</z>

</numbers>

Lines A through N of the stylesheet each make (or attempt to make) a different calculation. These calculations use the numbers in the document above and some other numbers that are either hardcoded in the stylesheet or retrieved from functions that return numbers.


<xsl:stylesheetxmlns:xsl="http://www.w3.org/1999/XSL/Transform"

version="1.0">

<xsl:outputmethod="xml"omit-xml-declaration="yes"/>



<xsl:templatematch="numbers">

A.4+3.2=<xsl:value-ofselect="x+y"/>

B.3.2-4=<xsl:value-ofselect="y-x"/>

C.4*3.2=<xsl:value-ofselect="x*y"/>

D.11/3.2=<xsl:value-ofselect="zdivy"/>

E.4+3.2*11=<xsl:value-ofselect="x+y*z"/>

F.(4+3.2)*11=<xsl:value-ofselect="(x+y)*z"/>

G.11mod4=<xsl:value-ofselect="zmodx"/>

H.4+3.2+11=<xsl:value-ofselect="sum(*)"/>

I.floor(3.2)=<xsl:value-ofselect="floor(y)"/>

J.ceiling(3.2)=<xsl:value-ofselect="ceiling(y)"/>

K.round(3.2)=<xsl:value-ofselect="round(y)"/>

L.11+count(*)=<xsl:value-ofselect="11+count(*)"/>

M.3.2+string-length("3.2")=

<xsl:value-ofselect="y+string-length(y)"/>

N.11+"hello"=<xsl:value-ofselect="z+'hello'"/>

</xsl:template>



</xsl:stylesheet>

Before we talk about what each line is doing, let's look at the result of applying the stylesheet to the numbers document.


A.4+3.2=7.2

B.3.2-4=-0.8

C.4*3.2=12.8

D.11/3.2=3.4375

E.4+3.2*11=39.2

F.(4+3.2)*11=79.2

G.11mod4=3

H.4+3.2+11=18.2

I.floor(3.2)=3

J.ceiling(3.2)=4

K.round(3.2)=3

L.11+count(*)=14

M.3.2+string-length("3.2")=

6.2

N.11+"hello"=NaN

The stylesheet has a single template rule for the source tree's numbers element. This template has a series of xsl:value-of instructions whose select attributes use the values of the numbers element's x, y, and z child elements to do various kinds of math. Mathematical expressions like these can use the full power of XPath to say which element or attribute has a number they need; this stylesheet, however, is more concerned with demonstrating the range of mathematical operations available than with using fancy XPath expressions to retrieve elements and attributes from odd parts of a document.

Line A of the template adds the value of x (4) to the value of y (3.2) and puts their sum, 7.2, in the result tree. It's simple, straightforward, and shows that you're not limited to integers for stylesheet math.

Line B subtracts 4 from 3.2 for a result of -0.8. Negative numbers shouldn't pose any difficulties for XSLT processors.

Warning With some XSLT processors, the use of decimal numbers may introduce a tiny error. For example, the "3.2 - 4" in this example comes out as "-.7999999999999998" on some processors. While being off by .0000000000000002 isn't much, being off at all shows that math is not XSLT's strong point.

Line C multiplies 4 and 3.2, using the asterisk as the multiplication operator, for an answer of 12.8.

Line D divides the value of the z element, (11), by 3.2, showing an XSLT processor's ability to perform floating-point division. Although most programming languages traditionally use the slash character to represent mathematical division, XPath already uses the slash to separate the steps in an XPath location path (for example, wine/vintage to represent the vintage child element of the wine element). Accordingly, XPath and XSLT use the string "div" for division.

Lines E and F show how parentheses have the same effect on operator precedence that they have in normal math notation: without them, multiplication happens before addition, so that 4 + 3.2 * 11 = 4 + 35.2. With the parentheses around the "4+3.2", that happens first, so that (4 + 3.2) * 11 = 7.2 * 11.

Line G demonstrates the mod operator, which shows the remainder if you divide the first term by the second. The example shows that 11 mod 4 equals 3, because 4 goes into 11 twice with 3 left over. This operator is great for checking whether one number divides into another evenly; just check whether the larger number mod the smaller equals zero.

Line H demonstrates the sum() function. With a node list as an argument, it sums all the numbers in the list. In the example the asterisk means "all the children of the context node" -- the numbers element's x, y, and z children.

Lines I and J demonstrate the floor() and ceiling() functions. If you pass either of these an integer, they return that integer. If you pass floor() a non-integer, it returns the highest integer below that number. In the example, floor(3.2) is 3. The ceiling function returns the smallest integer above a non-integer number; in the example, ceiling(3.2) equals 4.

Line K's round() function rounds off a non-integer by returning the closest integer. When 3.2 is passed to it, it returns 3; passing 3.5 or 3.6 to it would cause it to return 4.

Line L incorporates another XPath function, count(), which returns the number of nodes in the set passed to it as an argument. XPath offers several functions that, while not explicitly mathematical, return numbers and can be used for any calculations you like: count(), last(), position(), and string-length(). Line M demonstrates string-length(), which returns the length of a string.

    

Also in Transforming XML

Automating Stylesheet Creation

Appreciating Libxslt

Push, Pull, Next!

Seeking Equality

The Path of Control

Line N demonstrates what happens when you try to perform math with something that isn't a number: when 11 gets added to the string "hello", the result is the string "NaN", an abbreviation for "Not a Number." When you pull a number out of an element's content or attribute value and then use it for a calculation, you can't always be sure that what you pulled is really a number, so XSLT's clearly defined behavior for the unworkable case makes it easier to check for and cope with in your code.

XSLT is about manipulating text, not numbers, but you can build on the mathematical operations provided as part of XSLT to perform more complicated calculations. For example, the following stylesheet, which accepts any document as input, computes the value of pi. The precision of the result depends on the value of the iterations variable.


<xsl:stylesheetxmlns:xsl="http://www.w3.org/1999/XSL/Transform"

version="1.0">

<xsl:outputmethod="text"/>



<!--Computepi.BasedonLeibniz'salgorithmthat

pi/4=1-1/3+1/5-1/7+1/9-1/11...whichIdidas

pi=4-4/3+4/5-4/7+4/9-4/11...

-->



<xsl:variablename="iterations"select="80000"/>



<xsl:templatename="pi">

<!--namedtemplatecalledbymaintemplatebelow-->

<xsl:paramname="i">1</xsl:param>

<xsl:paramname="piValue">0</xsl:param>



<xsl:choose>

<!--Iftherearemoreiterationstodo,addthepassed

valueofpitoanotherroundofcalculations.-->

<xsl:whentest="$i&lt;=$iterations">

<xsl:call-templatename="pi">

<xsl:with-paramname="i"select="$i+4"/>

<xsl:with-paramname="piValue"

select="$piValue+(4div$i)-(4div($i+2))"/>

</xsl:call-template>

</xsl:when>



<!--Ifnomoreiterationstodo,add

computedvaluetoresulttree.-->

<xsl:otherwise>

<xsl:value-ofselect="$piValue"/>

</xsl:otherwise>



</xsl:choose>



</xsl:template>





<xsl:templatematch="/">

<xsl:call-templatename="pi"/>

</xsl:template>



</xsl:stylesheet>

The repetition is implemented using a recursive named template. With the iterations setting shown, the stylesheet creates this result:

3.1415676535897985

With that many iterations, the answer is only accurate up to the first four digits after the decimal. Of course, if you want to compute the value of pi seriously, there are many more appropriate languages, but it's nice to know that you can push XSLT to do some fairly complex math when necessary.

Close    To Top
  • Prev Article-XML:
  • Next Article-XML:
  • Now: Tutorial for Web and Software Design > XML > Styles > XML Content
    Photoshop Tutorial
     

    Special Effect

      3D Effect
      Photoshop Articles
    Programming Tutorial
     

    C/C++ Tutorial

      Visual Basic
      C# Tutorial
    Database Tutorial
     

    MySQL Tutorial

      MS SQL Tutorial
      Oracle Tutorial
    Geek Tutorial
     

    Blogging Tutorial

      RSS Tutorial
      Podcasting Tutorial
    Graphic Design Tutorial
      Coreldraw Tutorial
      Illustrator Tutorial
      3D Tutorials
    Webmaster Articles
     

    Domain Service

      Web Hosting
      Site Promotion
    Java Tutorial/ Articles
     

    Java Servlets

      JavaEE Tutorial
     

    JavaBeans Tutorial

    XML Tutorial/ Articles
     

    XML Style

      AJAX Tutorial
      XML Mobile
    Flash Tutorial/ Articles
     

    Flash Video

      Action Script
      Flash Articles
    OS Tutorial/ Articles
      Linux Tutorial
      Symbian Tutorial
      MacOS Tutorial
    Personal Tech
      Hardware Tutorial
      Software Tutorial
      Online Auction