Differences between revisions 60 and 61
| Deletions are marked like this. | Additions are marked like this. |
| Line 114: | Line 114: |
|
XPath expressions within the function body may refer to instance data, either through the initial XPath context, or through the instance() function. |
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
Function interface
Note: Much of the content below is borrowed from the XSLT 2.0 specification.
[Definition: An xforms:function declaration declares the name, parameters, and implementation of a function that can be called from any XPath expression within the XForms document.]
Element |
Attributes |
Minimal Content Model |
function |
Common, name, as? |
param*, variable*, sequence?* |
param |
Common, name, as? |
EMPTY |
variable |
Common, name, as?, select |
EMPTY |
sequence |
Common, select |
EMPTY |
<!-- Category: declaration --> <xforms:function name = qname-but-not-ncname as? = sequence-type> <!-- Content: (xforms:param*, variable*, sequence*) --> </xforms:function>
An xforms:function declaration can only appear as a top-level element in a model.
[TODO: does it make sense to allow declaring functions elsewhere?]
A custom function is included in the in-scope functions of the static context for all XPath expressions used in the document.
[TODO: should they be available only when the model is in scope? any other possibility here?]
The value of the name attribute is a QName but not an NCName. This means that a form author cannot add functions to the default function namespace.
[ED NOTE: For now we require that functions are in a namespace]
As defined in XPath, the function that is executed as the result of a function call is identified by looking in the in-scope functions of the static context for a function whose name and arity matches the name and number of arguments in the function call.
Note: Functions are not polymorphic. Although the XPath function call mechanism allows two functions to have the same name and different arity, it does not allow them to be distinguished by the types of their arguments.
The optional as attribute indicates the required type of the result of the function. The value of the as attribute is a SequenceType, as defined in [XPath 2.0].
[TODO: describe XPath 1.0 behavior]
If the as attribute is specified, then the result evaluated by the sequence constructor is converted to the required type, using the function conversion rules. It is a type error if this conversion fails. If the as attribute is omitted, the calculated result is used as supplied, and no conversion takes place.
The xforms:param elements define the formal arguments to the function. These are interpreted positionally. When the function is called using a function-call in an XPath expression, the first argument supplied is assigned to the first xforms:param element, the second argument supplied is assigned to the second xforms:param element, and so on.
The as attribute of the xforms:param element defines the required type of the parameter. The rules for converting the values of the actual arguments supplied in the function call to the types required by each xforms:param element are defined in [XPath 2.0]. The rules that apply are those for the case where XPath 1.0 compatibility mode is set to false.
[ERR] If the value of a parameter to a custom function cannot be converted to the required type, a type error is signaled.
If the as attribute is omitted, no conversion takes place and any value is accepted.
Within the body of a custom function, the focus is initially undefined; this means that any attempt to reference the context item, context position, or context size is a non-recoverable dynamic error. [XPDY0002]
It is not possible within the body of the custom function to access the values of local variables that were in scope in the place where the function call was written. Global variables, however, remain available.
<!-- Category: declaration --> <xforms:param name = qname as? = sequence-type/>
[ED NOTE: Like with XSLT 2, we do not allow optional parameters.]
The xforms:param element may be used as a child of xforms:function to define a parameter to a custom function, which may be supplied when the function is called from an XPath expression.
The xforms:param element has a required name attribute, which specifies the name of the parameter. The value of the name attribute is a QName.
[ERR] It is a static error if two parameters of a custom function have the same name.
The xforms:param element has an optional as attribute, which specifies the required type of the parameter.
[TODO: can the type really be optional? It is in XSLT 2.]
If the model is using XPath 1.0, the following types are available: string, boolean, number, nodeset, object.
If the model is using XPath 2.0, the XPath 2.0 types are available. The parameters from the function invocation are coerced to the types expected by the function parameters.
[TODO: check how parameter types must be handled.]
Function body
The function body contains an optional sequence of variables, followed by a constructor for the return value of the function.
The xforms:sequence element allows specifying a return value comprised or atomic values or nodes.
With XPath 1.0, xforms:sequence can only return a node-set or a single atomic value, due to the limits of XPath 1.0 expressions.
With XPath 1.0, only one xforms:sequence may be used.
XPath evaluation context
The initial XPath evaluation context in a custom function is the context applicable to the point where the function is declared, as described in Section 7.2 Evaluation Context.
XPath expressions within the function body may refer to instance data, either through the initial XPath context, or through the instance() function.
Examples
<function name="my:foo" as="number"> <param name="p" as="number"/> <param name="q" as="number"/> <sequence select="$p + $q"/> </function>
This is invoked in an XPath expression as my:foo(a, b).
Spec example: Need something like decimal-string() function
<function name="dollar-round" 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)"/> <sequence select="concat($intpart, '.', $fracpart)"/> </function>
Spec example: Need a sumproduct() function
<function name="my:sumproduct" as="number"> <param name="p" as="nodeset"/> <param name="q" as="nodeset"/> <sequence select="choose(count($p) = 0, 0, $p[1] * $q[1] + my:sumproduct($p[position() > 1], $q[position() > 1]))"/> </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.
Example: function selecting all elements called "name" in an instance.
<function name="my:get-names" as="nodeset">
<sequence select="//name"/>
</function>
Other questions