function makes it possible to perform a Boolean comparison and return an object (whether nodes or atomic types) based upon the results of that. For instance, suppose that you set up a binding in which the address structure given is different based upon whether the address is U.S. or Canadian. The binding would be expressed as <xf:bind id="address" calculate="compare(//locale='Canada',//address[country='Canada'],//address[country='US'])"/>
. Think of Compare()
as a superset of if()
, although if()
itself is being deprecated with an eye towards replacing it with the if
keyword from XPath 2.0 when XPath is incorporated into the next generation of the specification.
Two functions that can be a little confusing to differentiate are current() and context(). Current is primarily used in <xf:bind> statements in which a nodeset is defined. The current() function in this case is the specific node being evaluated from the nodeset. It's generally used in XPath predicate statements where the current context of evaluation differs from the context defined in the initial nodeset.
Consider this snippet:
<xforms:instance xmlns="" id="convTable">
<convTable date="20040212" currency="cdn">
In this example, current()will take each of the <mon> nodes from instance i1 and return them, comparing them against the @code attribute of the <month> elements. Notice here that the normal context operator "." that would be used in the predicate would reference the <month> element (technically the value attribute could be rendered as instance('i2')/month[./@code = current()]), and the lack of a current() function consequently made a number of XForms expressions difficult if not impossible to run.
The context() function is a little more complex, and it refers primarily to elements such as <xf:setvalue>. In the above example, the setvalue function has a specific @ref attribute that, when evaluated, points to the target for the @value attribute. The @value attribute in turn is set to this particular ref expression, which means that everything ends up being written relative to this @ref value, which can be problematic if that element is not even in the same instance as the current context. The context() function thus retains the evaluation context value outside of the <setvalue statement>, and can thus be used to provide information relative to this context, rather than to the @ref context.
For instance, suppose that you had the following instance:
<xf:instance xmlns="" id="i1">
<xf:instance xmlns="" id="i2">
Then context() would be used as follows:
<xf:setvalue ref="instance('i2')/result/c" value="context()/a + context()/b"/>
In this case, the default context from the ref that the value would end up using (instance('i2')/result/c) would prove useless in getting the a and b values (ordinarily, you would end up having to re-reference things back from the root, and a repeat element could prove to be unworkable). With context(), on the other hand, the context node for the expressions is the <store> element, which makes it possible to retrieve each of these values absolutely. Note that this has special utility within repeat statements, because context() will return the node of the most recent repeat context.
As a general rule, you would use current() in those situations where you're working with nodeset bindings, and context() when dealing with a ref statement that changes the immediate context (mainly <setvalue>).
Finally, the id() function is useful for retrieving content that has clearly defined IDs (i.e., any element that has a type of "xs:id"). The first argument is a space-separated list of IDs, and the second is a nodeset that describes the root directory from which to look for these resources (typically an instance() node). While it is typically used with a schema, it's also possible to bind elements directly:
<content id="mycontent">This is a block of content.</content>
<xf:bind nodeset="instance('i1')/*[@id]" type="xs:id"/>
Another function that introduces some very useful capabilities to XForms is the event() function. Whenever an event is launched, the user can catch and process that event with a <action> statement. In the context of that element (and only in that context), the event() function will return the requested property from the event string as a nodeset. For instance, when you do a submission, if an error occurs, you can get critical information using a number of properties, such as error-type, response-status-code, and response-reason-phrase, that can then be used for error alerts or updating a status field in the form:
<submission resource="https://example.com/getRecord" method="post" replace="instance" instance="record">
<message ev:event="xforms-submit-error">A submission error (<output value="event('error-type')"/>) occurred.</message>
Each event has its own set of message properties, and as such, you should consult the XForms 1.1 W3C Recommendation for full details.
These functions should simplify the process of binding and processing XForms content fairly dramatically. None of them is a radical departure from the existing model, but they do fill holes that were proving show-stoppers for most XForms implementations.