Custom XPath functions

From W3C XForms Group Wiki (Public)

Custom XPath Functions

Custom XPath functions are author-defined XPath functions that can be called from any XPath expression within the XForms document.


NOTE: The group had some agreement on the following guidelines on the 2009-10-28 call.


  • do not have side-effects (unless they call implementation-defined XPath functions which do have side-effects).
  • follow a syntax close to a subset of what XSLT 2 supports.
  • support a simple syntax, which can later be expanded (e.g. with something closer from XSLT 2's sequence constructors).
  • can be defined and used with XPath 1.0.
  • do not support calling XForms actions.
  • do not support creating local instances.


see XForms_2.0#The_function_Element


<function signature="my:foo($p as number, $q as number) as number">
   <sequence value="$p + $q"/>

This is invoked in an XPath expression as my:foo(a, b).

Spec example: Need something like decimal-string() function

<function signature="my:dollar-round($num as number) as string">
   <variable name="num100str" value="string(round($num * 100))"/>
   <variable name="trunc" value="substring-before($num100str, '.')"/>
   <variable name="intpart" value="substring($trunc, 0, string-length($trunc)-2)"/>
   <variable name="fracpart" value="substring($trunc, string-length($intpart), 2)"/>

   <sequence value="concat($intpart, '.', $fracpart)"/>

Spec example: Need a sumproduct() function

<function signature="my:sumproduct($p as number*, q as number*) as number">   
   <sequence select="sum(for $i in 1 to count($p) return $p[$i]*$q[$i])"/>

The set of 'price' children of each 'item' comprise the first parameter. The set of 'quantity' children of each 'item' comprise the second parameter. For each pair of price and quantity elements under an item, the product is computed. The result is the accumulated sum of the products.

Spec example: define function using javascript but with fallback to xpath if the XForms processor doesn't supports javascript

<function signature="my:foo($p as node()*) as number">
   <sequence select="sum($p)"/>
<function signature="my:foo($p as node()*) as number">
   <param name="p" as="nodeset"/>
   <script type="text/javascript">

The second function declaration of my:foo will override the first one if the processor supports javascript.

Other questions