XML - Use node-set() Function And Exist To Calculate Totals


For as powerful as XSLT can be, you may find yourself surprised that some trivial tasks can at first appear difficult to accomplish. A good example of this is calculating a total price from an invoice. In this example, we'll use the node-set() extension function to perform a total invoice calculation:


  • ?xml version="1.0" endocing=utf-8"?> (put a < in front of the ?)
  • Invoice> (put a < in front of the I)
  • Item> (put a < in front of the I)
  • Description>Beer (put a < in front of the D)
  • Quantity>6 (put a < in front of the Q)
  • UnitPrice>1.69 (put a < in front of the U)
  • /Item> (put a < in front of the /)
  • Item> (put a < in front of the I)
  • Description>Nacho Chips(put a < in front of the D)
  • Quantity>3 (put a < in front of the Q)
  • UnitPrice>0.99(put a < in front of the U)
  • /Item> (put a < in front of the /)
  • Item> (put a < in front of the I)
  • Description>Salsa Chips(put a < in front of the D)
  • Quantity>2 (put a < in front of the Q)
  • UnitPrice>1.19(put a < in front of the U)
  • /Item> (put a < in front of the /)
  • /Invoice> (put a < in front of the /)

To solve this problem, we'll need to use extension functions, which require a separate namespace. First, we need to declare the namespace as an extension to our stylesheet:


  • xsl :stylesheet version="1.0" (put a < in front of the x)
  • xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  • xmlns:exsl="http://exslt.org/common"
  • extension-element-prefixes="exsl">

To calculate the total price, we need to calculate the subtotals by multiplying each item price by the quantity purchased. The variable below stores the subtotals for each item into a node list of <number> elements. Basically, we've now assigned a result tree fragment, or "chunk" of XML code, to a variable directly:


  • xsl :variable name="subTotals"> (put a < in front of the x)
  • xsl :for-each select="//Item"> (put a < in front of the x)
  • number> (put a < in front of the n)
  • xsl :value-of select="Quantity * UnitPrice"/> (put a < in front of the x)
  • /number> (put a < in front of the /)
  • /xsl :for-each> (put a < in front of the /)
  • /xsl :variable> (put a < in front of the x)

To calculate the total sum, we must add the values of each item subtotal. The following variable adds up the sum of the subtotals using node-set function:


  • xsl :variable name="total"> (put a < in front of the x)
  • xsl :value-of select="sum(exsl : (put a < in front of the x)
  • node-set($subTotals)/number)"/>
  • /xsl :variable> (put a < in front of the /)

When the following stylesheet is applied to the invoice, you should see 15.489999999999998:


  • ?xml version="1.0"?> (put a < in front of the ?)
  • xsl :stylesheet version="1.0" (put a < in front of the x)
  • xmlns :xsl="http://www.w3.org/1999/XSL/Transform"
  • xmlns :exsl="http://exslt.org/common"
  • extension-element-prefixes="exsl">
  • xsl :template match="/"> (put a < in front of the x)
  • xsl :variable name="subTotals"> (put a < in front of the x)
  • xsl :for-each select="//Item"> (put a < in front of the x)
  • number> (put a < in front of the n)
  • xsl :value-of select="Quantity * UnitPrice"/> (put a < in front of the x)
  • /number> (put a < in front of the /)
  • /xsl :for-each> (put a < in front of the /)
  • /xsl :variable> (put a < in front of the /)
  • xsl :variable name="total"> (put a < in front of the x)
  • (put a < in front of the x)
  • /xsl :variable> (put a < in front of the /)
  • xsl :value-of select="$total"/> (put a < in front of the x)
  • /xsl :template> (put a < in front of the /)
  • /xsl :stylesheet> (put a < in front of the /)

Go back