3.4 Computed Expressions

The preceding section discussed how addressing works in XPath. The language is also capable of performing simple computations that return strings, booleans, or numbers. XForms defines the term Computed Expression to represent this special usage of XPath.

Datatypes in XPath and XForms

The term datatype can get a little confusing during discussions on XForms, since both XPath and XML Schema contain the notion of a datatype and the two don't always agree on the details.

XPath expressions have four major datatypes: node-sets, strings, booleans, and numbers. (Note that only the expressions contain the notion of datatypes, and the Data Model itself is datatype free, although early drafts of XPath 2.0 appear to change this) Of these, string and boolean are similar to the XML Schema datatypes of the same name, although XML Schema booleans differ in that they allow both "1" and "true" for true, and "0" and "false" for false. Because of this, hacky workarounds are sometimes needed, as described later. The number datatype in XPath represents a double-precision floating point number under the rules defined by the IEEE (which includes positive and negative infinity, positive and negative zero, and a special 'not a number' value), and is thus comparable with the XML Schema datatype double. Node-sets do not have a convenient analog in XML Schema.

One other convention you might run into in the XPath specification is a datatype called "object", which simply means 'any datatype'. The XPath function descriptions below use this same convention.

It's unusual to run into type conflicts in XPath, mainly because the flexible type conversion rules, which are defined below as the functions string( ), number( ), and boolean( ), tend to stay out of your way. In short, nearly any time a specific datatype is expected, a different datatype will get automatically converted into the expected datatype. For example, the expression "a/b * a/c" might seem to multiply two node-sets, at first glance. This works as expected, however, since the multiplication operator first converts each node-set into a number, then multiplies to arrive at a result (just as if the expression had been "number(a/b) * number(a/c)"). Operators and function parameters in XPath behave this way, which avoids a lot of pain for those who need to write XPath expressions.

3.4.1 Operators

3.4.1.1 Arithmetic basics (+, -, *, div, and mod)

XPath includes all the arithmetic basics: plus, minus, multiply, divide, modulus, and unary minus (which negates the single operand). All of these operators convert their operands into numbers if needed, as with a call to number( ).

Order of Precedence

Any time an expression uses more than one operator, it is necessary to know what precedence is used. For XPath, this is (lowest to highest, with semicolons as separators where necessary):

  1. or

  2. and

  3. =; !=

  4. <=; <; >=; >

  5. +; -

  6. *; div; mod; unary -

  7. | (union)

Operators at the same precedence level are always evaluated left-to-right. Parentheses can be used to force the expression to evaluate in a different order than the default.

3.4.1.2 Equality comparisons (=and !=)

Comparing whether one thing is the same as another or not is straightforward, though some of the type combinations get interesting.

When comparing two node-sets, the comparison looks at the individual nodes. If any node in the left-hand node-set has a string-value that meets the equals or not-equals comparison with the string-value of any node in the right-hand node-set, the overall comparison succeeds. Similarly, if one side is a node-set and the other side is either a string or a number, the comparison will succeed if any node in the node-set meets the comparison. In comparing a boolean and any other datatype, the other datatype is converted as with a call to boolean( ) before comparison. Otherwise, if at least one object to be compared is a number, then the other object is converted as with a call to number( ) before comparison. Finally, comparisons between the same datatypes for strings, numbers, and booleans can be done directly.

3.4.1.3 Relational comparisons (<, >, <=, and =>)

The rules for relational comparisons follow the same rules as above when at least one operand is a node-set. In all other cases, both operands are converted if necessary into a number, as with a call to number( ) before comparison.

3.4.1.4 Boolean operations (or, and)

Boolean expressions can be connected together with logical or and and operators. (Note that not( ) is available also, but as a function, not an operator)

3.4.1.5 Node-set unions (|)

A final operator performs a union operation on a node-set. Note that the resulting node-set (like all node-sets) will contain no duplicate nodes.

3.4.2 Functions

XPath defines a number of built-in functions, and XForms adds a few more. This section lists every built-in function. Note that even though function parameters are unnamed in XPath, the descriptions below include parameter names for descriptive purposes.

position( )returns the context position from the expression evaluation

Defined in: XPath 1.0
Parameters: <none>
Return type: number

This example returns the 4th para element child of the context node (or an empty node-set if there is no 4th para element):

para[position()=4]
last( )returns the context size from the expression evaluation context

Defined in: XPath 1.0
Parameters: <none>
Return type: number

This example returns the last para element child of the context node:

para[position()=last()]
count( )returns the number of nodes in a node-set

Defined in: XPath 1.0
Parameters: node-set ns (required)
Return type: number

This example returns the number of item elements that are children of the items element:

count( items/item )
id( )returns a single node matching a document-unique ID

Defined in: XPath 1.0
Parameters: object obj (required)
Return type: node-set

Normally, this function is used to return the single node with an ID that matches the string value passed in as a parameter. When a space-separated list or a node-set is passed in, it will return the union of all nodes that individually match the IDs. This function normally appears on the left-hand side of a path expression.

Determining what is a 'unique' ID is harder than it looks.

The XPath 1.0 Recommendation states that "If a document does not have a DTD, then no element in the document will have a unique ID." In XForms, a DTD will never be associated with instance data. An XML Schema, however, has a datatype called xs:ID, which can be associated with an instance data node to provide an indication that the node contains a unique id. Thus, it is still possible for the id( ) function to be useful in XForms, though it takes a little extra work.

This example selects the element with the unique ID "taxtable" (if any) and returns a node-set of all the rate element children:

id("taxtable")/rate
local-name( )returns the local part of the name of a node, without regard to any XML namespace

Defined in: XPath 1.0
Parameters: node-set ns (optional)
Return type: string

Only the first node (in document order) of the node-set is considered. When called with no parameters, the local name of the context node is returned.

This example returns the local name of the element xforms:model, which is "model":

local-name(xforms:model)
namespace-uri( )returns the namespace URI of a the name of a node, without regard to the local name

Defined in: XPath 1.0
Parameters: node-set ns (optional)
Return type: string

Only the first node (in document order) of the node-set is considered. For anything other than attribute and element nodes, the return value will always be the empty string. When called with no parameters, the namespace URI of the context node is returned.

This example returns the namespace URI of the element xforms:model, which is http://www.w3.org/2002/xforms:

namespace-uri(xforms:model)
name( )for element and attribute nodes, returns the node name as a QName

Defined in: XPath 1.0
Parameters: node-set ns (optional)
Return type: string

For other node types, returns the same value as local-name( ). When called with no parameters, the name of the context node is returned.

This example returns the QName of the element xforms:model, which is "xforms:model":

name(xforms:model)
string( )converts another datatype into a string

Defined in: XPath 1.0
Parameters: object str (optional)
Return type: string

Conversion from other datatypes proceeds according to the following rules:

node-set

The string-value of the node-set (which is the concatenation of the string-value of all descendant nodes) is returned.

number

A string representing the number is returned, or one of the special values of Infinity, -Infinity, or NaN (short for not a number).

boolean

Either true or false is returned.

When called with no parameters, the converted value of the context node is returned.

This example returns a string equal to the string-value of the title element, which in HTML would be a single text node:

string(/html/head/title)
concat( )returns the concatenation of all the string parameters

Defined in: XPath 1.0
Parameters: string s1 (required); string s2 (required); any number of additional optional strings
Return type: string

The example combines all four string parameters into a single string, "Hello World!":

concat( 'Hello', ' ', 'World', '!')
starts-with( )returns true if the src string starts with the substr string

Defined in: XPath 1.0
Parameters: string src (required); string substr (required)
Return type: boolean

This example returns true:

starts-with('Hello World!', 'H')
contains( )returns true if the src string contains the substr string

Defined in: XPath 1.0
Parameters: string src (required); string substr (required)
Return type: boolean

This example returns true:

contains('Hello World!', 'r')
substring-before( )returns the portion of the src occurring before the substr string

Defined in: XPath 1.0
Parameters: string src (required); string substr (required)
Return type: string

If the substr string is found within the larger string, this function returns the portion of the src string up to and not including the first matched substr. If not found, returns the empty string.

This example returns the string "1999":

substring-before("1999-04-01","-")
substring-after( )returns the portion of the src occurring after the substr string

Defined in: XPath 1.0
Parameters: string src (required); string substr (required)
Return type: string

If the substr string is found within the larger string, this function returns the portion of the src string after and not including the first matched substr string. If not found, returns the empty string.

This example returns the string "04-01":

substring-after("1999-04-01","-")
substring( )returns a selected substring of the src string

Defined in: XPath 1.0
Parameters: string src (required); number start (required); number length (optional)
Return type: string

The returned substring is determined by starting with the startth character, and continuing on for length characters. If the length parameter is omitted, the returned string continues on to the end of the src string.

The following example returns "34", and the second following example returns "345":

substring("12345", 3, 2) substring("12345", 3)
string-length( )returns the number of characters in the src string

Defined in: XPath 1.0
Parameters: string src (optional)
Return type: number

When called with no parameters, returns the number of characters in the context node converted to a string.

This example returns 12:

string-length("Hello World!")
normalize-space( )returns the src with certain whitespace characters collapsed

Defined in: XPath 1.0
Parameters: string src (optional)
Return type: string

This function removes all leading and trailing whitespace, and all other consecutive whitespace characters are replaced with a single space. When called with no parameters, returns the normalized value of the context node converted to a string.

This example returns "Hello World!":

normalize-space("  Hello   World!   ")
translate( )returns the src string, with characters replaced from a list

Defined in: XPath 1.0
Parameters: string src (required), string removechars (required), string replacechars (required)
Return type: string

Characters from the removechars string replaced with characters from the corresponding position in the replacechars string. The removechars string may be longer than the replacechars string, in which case the additional characters are simply removed from the src string.

In many languages, translate( ) can be used to perform case conversion. For example, to convert English to uppercase, the call you need would be translate(src, "abcdefghijklmnopqrstuvwxyz", "ABCDEFGHIJKLMNOPQRSTUVWXYZ").

A future edition of XPath may include specific functions for case conversion.

The first example returns "hello world!", and the second example returns "hello world" (note that the exclamation point is gone):

translate("Hello World!", "HW", "hw") translate("Hello World!", "HW!", "hw")
boolean( )converts another datatype into a boolean

Defined in: XPath 1.0
Parameters: object bool (optional)
Return type: boolean

Other datatypes are converted according to the following rules:

node-set

An empty node-set produces false; anything else produces true.

number

Zero and NaN produce false; anything else produces true.

string

An empty string produces false; anything else produces true.

When called with no parameters, the converted value of the context node is returned.

This example returns true if the Location Path a/b happens to select one or more nodes; otherwise, it returns false:

boolean(a/b)
not( )returns the logical negation of the argument

Defined in: XPath 1.0
Parameters: boolean b (required)
Return type: boolean

This example returns false if the Location Path a/b happens to select one or more nodes; otherwise, it returns true:

not(a/b)
true( )returns true

Defined in: XPath 1.0
Parameters: none
Return type: boolean

This example returns true:

true(  )
false( )returns false

Defined in: XPath 1.0
Parameters: none
Return type: boolean

This example returns false:

false(  )
lang( )checks the language of the context node

Defined in: XPath 1.0
Parameters: string langcode (required)
Return type: boolean

This function examines the context node and returns true if the declared language (with an xml:lang attribute) matches. The comparison takes into account the rules for language identifiers, such that a search for "en" will still match "en-gb". If the context node doesn't contain an xml:lang attribute, the nearest ancestor element node with an xml:lang attribute will be consulted. If no xml:lang declaration can be located, the return value is false.

For an XPath data model matching the following XML:

<root xml:lang="x-klingon">   <context/> </root>

With context as the context node, this example returns true:

lang("x")
number( )converts another datatype into a number

Defined in: XPath 1.0
Parameters: object num (required)
Return type: number

Other datatypes are converted according to the following rules:

string

A string that represents a number (ignoring leading and trailing whitespace) is converted into a number. Any string that can't be converted this way results in a return value of NaN.

boolean

true produces 1 and false produces 0.

node-set

A node-set is first converted into a string (as with string( )), then converted into a number by the rules for a string.

When called with no parameters, the converted value of the context node is returned.

The following example returns NaN:

number("three")
sum( )returns the sum of all the nodes in the node-set operands

Defined in: XPath 1.0
Parameters: node-set operands (required)
Return type: number

The value of each individual node is determined by converting the string-value to a number (as with number( )). If any individual node converts to NaN, the overall result is NaN.

For an XPath data model representing the following XML:

<operands>   <operand>3.14</operand>   <operand>42</operand>   <operand>0</operand>   <operand>0.86</operand> </operands>

The following XPath expression returns 46:

sum(/operands/operand)
floor( )returns the largest integer not greater than the num parameter

Defined in: XPath 1.0
Parameters: number num (required)
Return type: number

(NaN, Infinity, and -Infinity are passed through unchanged.)

The first example returns 3, and the second example returns -4:

floor(3.14) floor(-3.14)
ceiling( )returns the smallest integer not less than the num parameter

Defined in: XPath 1.0
Parameters: number num (required)
Return type: number

(NaN, Infinity, and -Infinity are passed through unchanged.)

The first example returns 4, and the second example returns -3:

ceiling(3.14) ceiling(-3.14)
round( )returns the integer closest to the num parameter

Defined in: XPath 1.0
Parameters: number num (required)
Return type: number

In the event of a tie, the larger result is returned. NaN, Infinity, and -Infinity are passed through unchanged.

The first example returns 4. The second example returns -3.

round(3.5) round(-3.5)
boolean-from-string( )converts a string value into a boolean

Defined in: XForms 1.0
Parameters: string bool (required)
Return type: boolean

This function differs from boolean( ) in that it takes into account XML Schema rules: "true" or "1" produces true, and "false" or "0" produce false.

This example, as might be used when the value of the b element is of the type xs:boolean, returns an XPath boolean value that matches the XML Schema value of the node:

boolean-from-string(a/b)
if( )evaluates an expression, returning two possible strings depending on the result

Defined in: XForms 1.0
Parameters: boolean test (required); string trueval (required); string falseval (required)
Return type: string

This function evaluates the boolean test parameter, and returns trueval if the test is true, or falseval otherwise. Note that all three parameters are always evaluated no "short circuit" evaluation takes place.

If the evaluation of a/b yields true, this example returns "it worked", and otherwise returns "it failed":

if(boolean-from-string(a/b), "it worked", "it failed")
avg( )returns the average of all the nodes in the node-set operands

Defined in: XForms 1.0
Parameters: node-set operands (required)
Return type: number

The average is computed as the sum( ) divided by the count( ) of the value of each individual node, converted into a number (as with number( )).

For an XPath data model representing the following XML:

<operands>   <operand>3.14</operand>   <operand>42</operand>   <operand>0</operand>   <operand>0.86</operand> </operands>

The following XPath expression returns 11.5:

avg(/operands/operand)
min( )returns the smallest of all the nodes in the node-set operands

Defined in: XForms 1.0
Parameters: node-set operands (required)
Return type: number

The value of each individual node is determined by converting the string-value to a number (as with number( )). A node-set that is empty or that includes nodes that evaluate to NaN will result in a return value of NaN.

For an XPath data model representing the following XML:

<operands>   <operand>3.14</operand>   <operand>42</operand>   <operand>0</operand>   <operand>0.86</operand> </operands>

The following XPath expression returns 0:

min(/operands/operand)
max( )returns the largest of all the nodes in the node-set operands

Defined in: XForms 1.0
Parameters: node-set operands (required)
Return type: number

The value of each individual node is determined by converting the string-value to a number (as with number( )). A node-set that is empty or that includes nodes that evaluate to NaN will result in a return value of NaN.

For an XPath data model representing the following XML:

<operands>   <operand>3.14</operand>   <operand>42</operand>   <operand>0</operand>   <operand>0.86</operand> </operands>

The following XPath expression returns 42:

max(/operands/operand)
count-non-empty( )returns the count of all the non-empty nodes in the node-set operands

Defined in: XForms 1.0
Parameters: node-set operands (required)
Return type: number

For the purposes of this function, "non-empty" means a string-value of one or more characters. This can be useful when computing an average that disregards empty values.

For an XPath data model representing the following XML:

<operands>   <operand>3.14</operand>   <operand>42</operand>   <operand/>   <operand>0.86</operand> </operands>

The following XPath expression returns 15.333333333333334:

sum(/operands/operand) div count-non-empty(/operands/operand)
index( )returns the current index for a given repeat set

Defined in: XForms 1.0
Parameters: string repeat-idref (required)
Return type: number

XForms includes the notion of repeating content that holds a current index. This function is an accessor for that index.

A full example requires a "repeating structure" setup with XForms user interface markup. Further information and examples are available in Chapter 6.

property( )returns the value of a given XForms property

Defined in: XForms 1.0
Parameters: string propname (required)
Return type: string

XForms specifies certain property strings that can be retrieved with this function:

  • version returns the XForms version number

  • conformance-level returns the XForms conformance level, either "basic" or "full"

This example returns 1.0, assuming the processing environment claims to be XForms 1.0 compliant:

property("version")
now( )returns the current system date and time

Defined in: XForms 1.0
Parameters: none
Return type: string

The format returned by this function is a lexical XML Schema xs:dateTime format. If time zone information is unavailable from the system, an implementation default is used so that comparisons will still work.

This example returns 2003-02-14T09:13:02Z, when called at that point in time:

now(  )
instance( )provides access to an alternate XForms instance

Defined in: XForms 1.0
Parameters: string instance-idref (required)
Return type: node-set

XPath allows multiple separate instance data areas. This function returns the root node of the specified instance data. Normally, this function appears on the left-hand side of a path expression.

This example returns a node-set consisting of the rate element node from the instance named "taxtable":

instance('taxtable')/rate
days-from-date( )converts an XML Schema xs:date into a signed whole number of days

Defined in: XForms 1.0
Parameters: string date (required)
Return type: number

This function computes a number of days relative to an epoch of 1970-01-01, and is most useful when two xs:date values need to be compared.

This example returns -1:

days-from-date("1969-12-31")
seconds-from-dateTime( )converts an XML Schema xs:dateTime into a number of seconds

Defined in: XForms 1.0
Parameters: string dateTime (required)
Return type: number

This function computes a signed fractional number of seconds relative to an epoch of 1970-01-01T00:00:00Z, and is useful when two xs:dateTimes need to be compared.

This example returns the large number of seconds representing the current date and time:

seconds-from-dateTime(now())
seconds( )normalizes a dayTimeDuration into a number of seconds

Defined in: XForms 1.0
Parameters: string dayTimeDuration (required)
Return type: number

This function computes a fractional number of seconds that is equivalent in length to the dayTimeDuration parameter (formatted according to XML Schema rules).

This function makes the distinction of working on a dayTimeDuration, which is a more fine-grained datatype than defined by XML Schema. Chapter 4 discusses this in greater detail.

This example returns 297001.5:

seconds("P3DT10H30M1.5S")
months( )normalizes a yearMonthDuration into a number of months

Defined in: XForms 1.0
Parameters: string dayTimeDuration (required)
Return type: number

This function computes a whole number of months that is equivalent in length to the yearMonthDuration parameter (formatted according to XML Schema rules).

This function makes the distinction of working on a yearMonthDuration, which is a more fine-grained datatype than defined by XML Schema. Chapter 4 discusses this in greater detail.

This example returns 14:

months("P1Y2M")
3.4.2.1 Extension Functions

The XPath specification itself is silent on the issue of implementation-specific or "extension" functions. XSLT, on the other hand, defines a framework in which extension functions can be used. Similarly, XForms provides a general outline of how extension functions fit in.

Extension functions are easily recognizable since all built-in functions are unprefixed names, while all extension functions contain a leading prefix and a colon character. A group of volunteers at the web site http://www.exslt.org/ collect and maintain a number of extension functions that are suitable for use in XForms.

The main disadvantage of extension functions is non-portability. Since these functions are implementation-specific, any form that uses them will only work inside implementations that also support the functions used. To make this explicit, any form that uses extension functions should list the QNames of the functions in the functions attribute of the model element. For example, a form that needed a few more date and time functions from the EXSLT library would use the following declaration:

<xforms:model xmlns:exslt="http://exslt.org/dates-and-times" functions="exslt:leap-year exslt:month-name exslt:day-name"> ...

Upon initialization, the XForms Processor will check to make sure that all the listed functions are available and immediately signal an error if they are not. For this reason, only functions that are absolutely necessary to the proper functioning of the form should be listed here. On the other hand, failing to list a function here will likely cause a run-time XPath error in some implementations, such as when the user is filling out the form and gets to the point where the XPath engine will try (and fail) to locate the extension function.



XForms Essentials
Xforms Essentials
ISBN: 0596003692
EAN: 2147483647
Year: 2005
Pages: 117
Authors: Micah Dubinko

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net