7 Dynamic Constraints


Contents

This chapter is normative.

7.1 Introduction

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.

Note: For simplicity, this chapter currently defines DCL as being based on XPath without subsetting. 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].

7.2 Datatypes

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.

Note: Resource-limited XForms Processors may define implementation limits on the maximum size of a node-set.

Issue: 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.

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.

[Ed: The productions here currently do not properly reference and extend those found in XPath.]

[1] Digit    ::=    [0-9]  
[2] HexDigit    ::=    Digit
| ['a' - 'f']
| ['A' - 'F']
 
[3] NullExp    ::=    'null'  
[4] BoolExp    ::=    'true' | 'false'  
[5] NumberExp    ::=    0x[HexDigit]+
| [['-']Digit+['.' Digit*] [('e' | 'E')['+' | '-']Digit+]
 
[6] StringExp    ::=    '"' NCName? '"' | "'" NCName? "'"  
[7] ArrayExp    ::=    '[]' | [Expr [',' Expr]*]  

7.3 Addressing

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:

Many programming languages, including ECMAScript and Java, use zero rather than one for the index number for the first item in an array. 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:

To address the partNum attribute in the second item you could write:

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:

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.

[8] Identifier    ::=    (('/'
| '../'
| element-name) ['[' Expr ']'])+
 
[9] PathExp    ::=    identifier ['@' attribute-name]
| '@' attribute-name
 

7.3.1 Data Spaces

XForms applications may need access to data beyond that immediately present in an XForms Model. Some possible examples include: the user's locale, information about the XForms Processor's capabilities, the user's name and address, location information for a mobile device, and temporary data which won't be submitted to the server. The XForms application may be part of a suite of applications that share a common data context. An architecture is needed that describes the relationship between data spaces as well as the access control mechanisms needed for security and privacy.

A given constraint may need to refer to multiple data spaces. There are several ways in principle that this could be achieved:

Note that XML namespaces solve a different problem. XPath permits the use of an XML namespace prefix for element names, but the element is still assumed to be in the same node tree. XML namespaces provide a way for XML documents to distinguish elements which have the same name but different semantics.

7.4 Operators

A small amount of 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:

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:

The and, or and xor require Boolean operands and perform the corresponding Boolean operations. For instance, the following examples are all 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:

The % operator is a postfix operator that divides its operand by 100.

The = operator performs assignment. The mechanism for binding XForms User Interface controls generally assumes that each form control is bound to a single model item. Some 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:

[10] InfixOperator    ::=    'and'
| 'or'
| 'xor'
| 'plus'
| 'minus'
| 'times'
| 'over'
| 'is' [[PrefixOperator] ('above' | 'below' | 'before' | 'after')]
 
[11] InfixExp    ::=    Expr InfixOperator Expr  
[12] PrefixOperator    ::=    'not'  
[13] PrefixExp    ::=    PrefixOperator Expr  
[14] PostfixOperator    ::=    '%'  
[15] PostfixExp    ::=    Expr PostfixOperator  
[16] SpecialOperator    ::=    'is' ['not'] 'within'  
[17] SpecialExp    ::=    Expr SpecialOperator '(' Expr ',' Expr ')'  
[18] IfThenElseExp    ::=    'if' Expr 'then' Expr ['else' Expr]  
[19] Assignment    ::=    [Lexpr '=' ]+ Expr [ ';' Assignment ]* [ ';' ]  
[20] Lexpr    ::=    Identifier |
Function |
(Lexpr)
 

7.5 XForms Core Function Library

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]*] ')'  

7.5.1 XPath Core Function Library

The XForms Core Function Library includes the entire [XPath] Core Function Library, including operations on node-sets, strings, numbers, and booleans.

Further input is required on the ability for resource-constrained devices to implement the complete XPath Core Function Library.

7.5.2 Number Methods

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.

7.5.3 String Methods

Note: the following are defined within [XPath] - string(), concat(), starts-with(), contains(), substring-before(), substring-after(), substring(), string-length(), normalize-space(), and translate().

7.5.4 Date/Time Methods

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.

7.5.5 Miscellaneous Methods

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.

7.6 Lexical Structure

When tokenizing, the longest possible token is always returned.

White space is permitted between tokens with the following exceptions:

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
 

7.7 Extensibility

This section will be expanded in future revisions, to cover extension functions and methods for calling out to script.