Custom XPath functions: Difference between revisions

From W3C XForms Group Wiki (Public)
forms>Johnboyer
No edit summary
Nvandenb (talk | contribs)
 
(55 intermediate revisions by 5 users not shown)
Line 2: Line 2:
= Custom XPath Functions =
= Custom XPath Functions =


It is possible to add XPath functions to an form using the processor's capabilities.
Custom XPath functions are author-defined XPath functions that can be called from any XPath expression within the XForms document.


For example, a set of XForms actions could be given a function name and invoked from XPath.
== Guidelines ==


The evaluation context for XPaths in the actions would be set to an implicit empty instance node, and the instance() function would not work for XPaths within an XForms function definition.  This prevents function side-effects.
''NOTE: The group had some agreement on the following guidelines on the 2009-10-28 call.''


The function parameters would appears as XPath variables, and more variables could be declared.
Functions:
 
* 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.
 
== Syntax ==
see [[XForms_2.0#The_function_Element]]
 
== Examples ==




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




This would be invoked in an XPath simply as xflocal:foo(p, q)
This is invoked in an XPath expression as <code><nowiki>my:foo(a, b)</nowiki></code>.


Spec example: Need something like [[decimal-string() function]]
Spec example: Need something like [[decimal-string() function]]
Line 28: Line 36:


<pre><nowiki>
<pre><nowiki>
<function name="dollar-round" as="string">
<function signature="my:dollar-round($num as number) as string">
   <param name="num" as="number"/>
  <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)"/>


   <variable name="num100str" as="string" value="string(round(num * 100))"/>
   <sequence value="concat($intpart, '.', $fracpart)"/>
</function>
</nowiki></pre>


  <variable name="trunc" as="string" value="substring-before($num100str, '.')"/>


  <variable name="intpart" as="string" value="substring($trunc, 0, string-length($trunc)-2)"/>
Spec example: [[Need a sumproduct() function]]


  <variable name="fracpart" as="string" value="substring($trunc, string-length($intpart), 2)"/>


   <return value="concat($intpart, '.', $fracpart)"/>
<pre><nowiki>
</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])"/>
</function>
</nowiki></pre>
</nowiki></pre>




Spec example: [[Need a sumproduct() function]]
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


<pre><nowiki>
<pre><nowiki>
<function name="sumproduct" as="number">
<function signature="my:foo($p as node()*) as number">
  <sequence select="sum($p)"/>
</function>
<function signature="my:foo($p as node()*) as number">
   <param name="p" as="nodeset"/>
   <param name="p" as="nodeset"/>
  <param name="q" as="nodeset"/>
  <variable name="counter" as="number">1</variable>
    
    
   <variable name="accumulator" as="number">0</variable>
   <script type="text/javascript">
 
       foo(XForms.var.p);
  <action if="count($p) = count($q)">
   </script>
       <action while="$counter &lt; count($p)">
</function>
        <setvalue name="accumulator" value="$accumulator + ($p[$counter] * $q[$counter])"/>
        <setvalue name="counter" value="$counter + 1"/>
      </action>
   </action>
 
  <return value="$accumulator"/>
</function
 
...
 
<output context="/purchaseOrder/items" value="xflocal:sumproduct(item/price, item/quantity)"/>
</nowiki></pre>
</nowiki></pre>


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


The set of 'price' children of each 'item' comprise the first parameter.
== Other questions ==
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.
 
''' Notes: '''
* Variables can be declared anywhere in the sequence.
* The name attribute is used in setvalue because ref must return a node
* Avoided putting local instance data for now for basic use cases
* Functions can be recursive
* Function names can be assigned a namespace by using a qname
* Function names that are NCName are in the namespace http://www.w3.org/2002/xforms/local-function#
* Functions declared and implemented in other languages (e.g. script, Java) are made available to XPath in the namespace http://www.w3.org/2002/xforms/local-function#


''' Questions: '''
== Inspiration ==


* How do we allow a function to build up nodesets to return?  How do we let those nodesets contain new nodes not in the original tree from which the input parameter nodesets are drawn?  How do we then restrict functions from modifying the node structures of the nodes passed as input?
* http://www.w3.org/TR/xslt20/#stylesheet-functions
* Do we want optional parameters?
* http://www.w3.org/TR/xquery/#FunctionDeclns
* Should we apply 'if' to return?  Is return an action or part of the function syntax?
* http://www.exslt.org/func/elements/function/index.html
* Should local instance be allowed now? If so, could insert nodesets from params and manipulate. Could return nodeset from params, but return local instance node is a problem.
* http://www.exslt.org/func/elements/script/index.html
* Seems like send, load, toggle, setindex, and setfocus should be forbidden?  Only data manipulator actions.
* http://www.w3.org/TR/xpath-30/#id-inline-func


----
----
[[Category:XFormsFutureFeatures]]
[[Category:XForms20]]

Latest revision as of 12:49, 15 March 2012

Custom XPath Functions

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

Guidelines

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

Functions:

  • 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.

Syntax

see XForms_2.0#The_function_Element

Examples

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


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)"/>
</function>


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])"/>
</function>


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>
<function signature="my:foo($p as node()*) as number">
   <param name="p" as="nodeset"/>
   
   <script type="text/javascript">
      foo(XForms.var.p);
   </script>
</function>

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

Other questions

Inspiration