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.
| ['a' - 'f']
| ['A' - 'F']
|||BoolExp||::=||'true' | 'false'|
| [['-']Digit+['.' Digit*] [('e' | 'E')['+' | '-']Digit+]
|||StringExp||::=||'"' NCName? '"' | "'" NCName? "'"|
|||ArrayExp||::=||'' | [Expr [',' Expr]*]|
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:
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
attribute in the
purchaseOrder element could be addressed as follows:
To address the
partNum attribute in the second item you could
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
partNum attribute could be addressed as follows:
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)]
| element-name) ['[' Expr ']'])+
|||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:
<instance>and therefore all child instance data)
<foo>element, which must be a child of
xform:refattribute. An XForms element is "outermost" when the XPath expression
ancestor::*includes no binding element nodes.
ancestor::*. This is also called "scoped resolution".
Scoped Binding Expressions
<someGroupingWidget ref="element1/foo/bar"> <anotherWidget ref="element2"/> <anotherWidget ref="@attr"/> </someGroupingWidget>
In this example, the
someGroupingWidgethas a binding expression of
element1/foo/bar. According to the rules above, this outermost element would have a context node of
/, which is the
<instance>element. Both of the
anotherWidgets then inherit a context node from their parent, the context node being
/element1/foo/bar. Based on this, the
anotherWidgetbinding expressions evaluate respectively to
/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:
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
not operator can only be used with an operand that
evaluates to a Boolean value. If the operand is
operator evaluates to
false. If the operand is
not operator evaluates to
else expr2 construct requires cond to evaluate
false. If cond is
the value of the construct is the result of evaluating expr1, otherwise
it is obtained from evaluating expr2.
is operator compares two values, and produces a Boolean
is within(expr1, expr2) construct
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.
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
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
3 is within(1,5)
3 is not within(1,2)
"aab" is within("aaa", "aac")
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
age is 60
26 is not 27
3 is below 4
"Mary" is after "Mandy"
Boolean operands and perform the corresponding Boolean operations. For instance,
the following examples are all
false is true and false
true is true or false
true is true xor false
false is true xor true
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
operator can also be applied to string operands, to perform string concatenation.
The following examples are all
5 is 1 plus 4
3 is 6 over 2
3 is 5 minus 2
"happy days" is "happy" plus " " plus "days"
% operator is a postfix operator that divides its operand
9 is 15% times 60
= 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:
| 'is' [[PrefixOperator] ('above' | 'below' | 'before' | 'after')]
|||InfixExp||::=||Expr InfixOperator Expr|
|||SpecialOperator||::=||'is' ['not'] 'within'|
|||SpecialExp||::=||Expr SpecialOperator '(' Expr ',' Expr ')'|
|||IfThenElseExp||::=||'if' Expr 'then' Expr ['else' Expr]|
|||Assignment||::=||[Lexpr '=' ]+ Expr [ ';' Assignment ]* [ ';' ]|
This section defines a set of required functions useful within XForms. Function syntax is based on XPath:
|||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().
Function: string now()
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.
Function: null submit()
The submit function immediately submits the instance data bound to the node that contains the expression.
Function: null reset()
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:
../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
. 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.
This section will be expanded in future revisions, to cover extension functions and methods for calling out to script.