This chapter is normative.
Many forms define integrity constraints that act over multiple fields. For example, the total value of an order can be defined in terms of a computation over other values such as unit prices, quantities, discounts, and tax and shipping costs. Such computations can be conveniently represented using the syntax outlined in here. This chapter describes an XForms Dynamic Constraints Language (DCL) based on XPath that enables these types of expressions without the use of a separate scripting language.
Dynamic Constraints are also useful for declaratively stating when a form control or subform needs to be filled out, according to some other value. A further use is to functionally define the acceptable choices for some form control, when this depends on other values.
Editor's Note: For simplicity, this chapter currently defines DCL as being based on XPath without subsetting. Readers should note, however, there is not yet consensus within the XForms Working Group on this matter. Specific points under consideration are noted throughout this chapter.
In the following grammar, the non-terminal NCName is defined in [XML Names], and S is defined in [XML 1.0].
XForms Dynamic Constraints are built out of the XForms data types:
The string, Boolean, and number types correspond to those defined in XPath. Dates, time durations and monetary values etc. are subtypes of string. Additionally, the XPath datatypes node-set and null are allowed in the XForms Dynamic Constraint Language.
Resource-limited XForms Processors may define implementation limits on the maximum size of a node-set.
[Editor's Feedback Request 6.2.conversions: XPath defines specific type conversions. The XForms Working Group is considering whether to include or exclude these as part of XForms Dynamic Constraints. Either way, there will be well-defined semantics of operations involving differing types. Comments from the community are welcome.]
If an operation cannot be performed an exception will be thrown. Exceptions are treated as events and can be caught using event handlers, declared in XML or in scripts.
Standalone XForms Datatypes are considered valid XForms Dynamic Constraints.
Editor's Note: The productions here currently do not properly reference and extend those found in XPath.
Like XPath, the XForms DCL models an XML document as a tree of nodes. There
are different types of nodes, including element nodes, attribute nodes and text
nodes. XPath uses '/
' as a location-step separator. XML doesn't
permit the '/
' character within element or attribute names, so
this is unambiguous.
XPath additionally allows an array index notation to address the n-th element in a sequence, for example, the line items in a purchase order.
<purchaseOrder orderDate="1999-10-20"> <item partNum="872-AA"> ... </item> <item partNum="926-AA"> ... </item> </purchaseOrder>
The second item in the purchase order could be addressed as follows:
purchaseOrder/item[2]
As in XPath, array indexes start at 1, not 0. Authors should be aware of this, especially when writing applications that combine scripting and XForms.
XPath also allows you to address attributes. For instance, the orderDate
attribute in the purchaseOrder
element could be addressed as follows:
purchaseOrder/@orderDate
To address the partNum
attribute in the second item you could
write:
purchaseOrder/item[2]/@partNum
As with XPath, all addressing is based on the concept of a context node. In
many situations, using a context node can lead to shorter identifiers. As an
example, if the second item
element above was selected as the context
node, the partNum
attribute could be addressed as follows:
@partNum
Identifiers are evaluated from left to right. The value of an identifier must resolve to one of the above types. The identifier syntax is a based on XPath and follows the same semantics. If an identifier starts with an element name, then the name must be in the current context (scope) or an ancestor context. If an identifier can't be resolved, an invalid identifier exception is thrown.
[Editor's Feedback Request 6.3.ns: To what extent do binding expressions need to concern themselves with namespaces? (Note that for authoring simplicity, this proposal so far largely treats binding expressions in a non-namespace-aware fashion)]
[8] | Identifier | ::= | (('/' | '../' | element-name) ['[' Expr ']'])+ |
|
[9] | PathExp | ::= | identifier ['@' attribute-name] | '@' attribute-name |
Binding expressions are often used to point to a specific instance data item. When used in this role, the following rules determine how data is selected:
<instance>
element. For example:
/
(selects <instance>
and therefore all
child instance data)/foo
(selects the <foo>
element, which
must be a child of <instance>
)xform:ref
attribute. An XForms element is "outermost" when the XPath expression
ancestor::*
includes no binding element nodes.ancestor::*
. This
is also called "scoped resolution".Example:
Scoped Binding Expressions
<someGroupingWidget ref="element1/foo/bar"> <anotherWidget ref="element2"/> <anotherWidget ref="@attr"/> </someGroupingWidget>In this example, the
someGroupingWidget
has a binding expression ofelement1/foo/bar
. According to the rules above, this outermost element would have a context node of/
, which is the<instance>
element. Both of theanotherWidget
s then inherit a context node from their parent, the context node being/element1/foo/bar
. Based on this, theanotherWidget
binding expressions evaluate respectively to/element1/foo/bar/element2
and/element1/foo/bar/@attr
. Matching instance data follows:
Sample Instance Data
<instance xmlns="http://www.w3.org/2001/02/xforms"> <element1 xmlns="..."> <foo> <bar attr="xyz"> <element2>xyz</element2> </bar> </foo> </element1> </instance>Here is a sample instance data that fits the above UI markup. "xyz" indicates sample data.
In some cases, binding expressions address the XForms Model, for instance to select dynamic constraints or calculations. This operates similar to the above.
Editor's Note: A future revision will explain this in greater detail, including an example.
As with XPath, it is possible to construct many different binding expressions that end up pointing to the same location. That said, it is often useful to express a binding expression in a standard, compact representation, called a canonical binding expression.
Canonical binding expressions are represented as a AbsoluteLocationPath as defined in [XPath]. Additionally, canonical binding expressions use only default axis-specifiers (for elements) or the '@' abbreviation (for attributes). Examples:
/a/b/c
/a/b/@c
a/b/c
child::a/child::b/child::c
/a/b/c/d/ancestor::c
Editor's Note: Some work is still needed to specify operator precedence, associativity and the event names thrown upon exceptions.
XPath reserves '/
' as a location-step separator, making it impractical
to also use this symbol for division. The Dynamic Constraints Language makes
consistent use of English names for operators is intended to minimize the potential
for authoring errors, and to avoid the need for using character entity references
for symbols.
The not
operator can only be used with an operand that
evaluates to a Boolean value. If the operand is true
, the not
operator evaluates to false
. If the operand is false
,
the not
operator evaluates to true
.
The if
cond then
expr1
else
expr2 construct requires cond to evaluate
to true
or false
. If cond is true
,
the value of the construct is the result of evaluating expr1, otherwise
it is obtained from evaluating expr2.
The is
operator compares two values, and produces a Boolean
result.
The expr is within
(expr1, expr2) construct
evaluates to true
if the result from evaluating expr falls
within the inclusive range defined by expr1 and expr2. If it falls
outside the range the construct evaluates to false
. The operands
must be of the same type, and are restricted to numbers, strings, dates, times
or monetary values with the same currency code. String comparison is defined
as per the Unicode standard.
The expr is not within
(expr1, expr2)
construct evaluates to false
if the result from evaluating expr
falls within the inclusive range defined by expr1 and expr2. If
it falls outside the range the construct evaluates to true
. The
operands must be of the same type, and are restricted to numbers, strings, dates,
times or monetary values with the same currency code. String comparison is defined
as per the Unicode standard. Here are some examples of true
statements:
3 is within(1,5)
3 is not within(1,2)
"aab" is within("aaa", "aac")
The is before
and related operators provide comparison
operations similar to is within
. The operands must be of
the same type, and are restricted to numbers, strings, dates, times or monetary
values with the same currency code. String comparison is defined as per the
Unicode standard. Before and below denote earlier in the scalar range, while
after and above denote later in the scalar range. For instance, here are some
examples of true
statements:
age is 60
26 is not 27
3 is below 4
"Mary" is after "Mandy"
The and
, or
and xor
require
Boolean operands and perform the corresponding Boolean operations. For instance,
the following examples are all true
:
false is true and false
true is true or false
true is true xor false
false is true xor true
The plus
, minus
, times
and over
operators require numeric operands (see below for exceptions) and perform the
corresponding arithmetic operations. The over
operator performs
division and throws an overflow exception if the denominator is zero. The plus
operator can also be applied to string operands, to perform string concatenation.
The following examples are all true
:
5 is 1 plus 4
3 is 6 over 2
3 is 5 minus 2
"happy days" is "happy" plus " " plus "days"
The %
operator is a postfix operator that divides its operand
by 100.
9 is 15% times 60
The =
operator performs assignment. The mechanism for binding
form controls generally assumes that each form
control is bound to a single model item.
Some XForms User Interface controls such as buttons and image-maps may need to set
the values of several model items in
the same action. It is proposed that this is handled using one or more assignment
statements separated by semicolons:
Here is a simple example which sets both the city and state:
city="London"; state="Ontario"
This section defines a set of required functions useful within XForms. Function syntax is based on XPath:
[21] | Arg | ::= | Expr | |
[22] | FunctionExp | ::= | function-name '('[arg [',' arg]*] ')' |
The XForms Core Function Library includes the entire [XPath] Core Function Library, including operations on node-sets, strings, numbers, and booleans.
Editor's Note: Further input is required on the ability for resource-constrained devices to implement the complete XPath Core Function Library.
Note: the following are defined within [XPath]
- number(), sum(), floor(), ceiling(), and round()
Function: number average(node-set)
The average function returns the arithmetic average value, for each node in the argument node-set, of the result of converting the string-values of the node to a number. Numbers are added with plus, and then taken over the count() of the specified node-set.
Function: number min(node-set)
The min function returns the minimum value, for each node in the argument node-set, of the result of converting the string-values of the node to a number. Numbers are compared with is below.
Function: number max(node-set)
The max function returns the arithmetic average value, for each node in the argument node-set, of the result of converting the string-values of the node to a number. Numbers are compared with is below.
Note: the following are defined within [XPath]
- string(), concat(), starts-with(), contains(), substring-before(), substring-after(),
substring(), string-length(), normalize-space(), and translate().
The now function returns the current system time as a string value, in the canonical format defined within the XForms specification. If local time zone information is available, it is included in the string.
The submit function immediately submits the instance data bound to the node that contains the expression.
The reset function immediately resets the instance data bound to the node that contains the expression.
When tokenizing, the longest possible token is always returned.
Whitespace is permitted between tokens with the following exceptions:
/
or ../
within compound identifiers.Whitespace is required between adjacent alphanumeric tokens, e.g. white space
is required between the operator "not
" and the name of a function.
Names follow the lexical rules for XML NAME tokens. Function names, however,
are not permitted to include -
or .
for compatibility
with externally defined functions.
Parentheses can be used for grouping, but otherwise have no effect on the semantics of Dynamic Constraints. The syntax caters for literals for null, booleans, numbers, and strings.
[23] | Expr | ::= | NullExp | BoolExp | NumberExp | StringExp | ArrayExp | PathExp | InfixExp | PrefixExp | PostfixExp | SpecialExp | IfThenElseExp |
This section will be expanded in future revisions, to cover extension functions and methods for calling out to script.