Automatic Type Conversions

In XQuery, each function and operator expects its arguments to be of a particular type. However, this is not as rigid as it may sound since there are a number of type conversions that happen automatically. They are discussed in this section.

Subtype Substitution

Functions and operators that expect a value of a particular type also accept a value of one of its derived types. This is known as subtype substitution. For example, the upper-case function expects an xs:string as an argument, but you can pass a value whose type is derived by restriction from xs:string, such as xs:NMTOKEN. This also works for complex types. A function expecting an element of type ProductType also accepts an element of type UmbrellaType, if UmbrellaType is derived by restriction from ProductType. Note that the value retains its original type; it is not actually cast to another type.

Type Promotion

When two values of different numeric types are compared or used in the same operation, one is promoted to the type of the other. An xs:decimal value can be promoted to the xs:float or xs:double type, and an xs:float value can be promoted to the xs:double type. For example, the expression 1.0 + 1.2E0 adds an xs:decimal value (1.0) to an xs:double value. The xs:decimal value is promoted to xs:double before the expression is evaluated. Numeric type promotion happens automatically in arithmetic expressions, comparison expressions, and function calls.

In addition, values of type xs:anyURI are automatically promoted to xs:string in comparison expressions and function calls. Unlike subtype substitution, type promotion results in the type of a value changing.

Casting of Untyped Values

In some cases, an untyped value is automatically cast to a specific type. This occurs in function calls, as well as in comparison and arithmetic expressions. For example, if you call the upper-case function with an untyped value, it is automatically cast to xs:string. If you add an untyped value to a number, as in <a>3</a> + 2, the untyped value 3 is cast to xs:integer, and the expression returns 5.

Note that typed values are not automatically cast. For example, "3" + 2 will not automatically cast the string 3 to the number 3, even though this is theoretically possible. One exception is the concat function, which automatically casts its arguments to strings. But that's special behavior of this particular function, not something that happens implicitly on the function call.

Atomization

Atomization occurs when a function or operator expects an atomic value and receives a node instead. Specifically, it is used in:

  • Arithmetic operations

  • Comparisons

  • Function calls and returns

  • Cast expressions and constructors

  • Name expressions in computed constructors

Atomization involves extracting the typed value of one or more elements or attributes to return one or more atomic values. For example:

<el>3</el> + 5

returns the value 8 because the value 3 is extracted from the el element during atomization. Also:

substring(<e2>query</e2>, 2, 3)

returns uer because the string query is extracted from the e2 element. These two examples work if e1 and e2 are untyped, because their so-called typed values would be instances of xs:untypedAtomic, and would be cast to the type required by the operation. They would work equally well if e1 had the type xs:integer, and e2 had the type xs:string, in which case no casting would need to take place.

Effective Boolean Value

It is often useful to treat a sequence as a Boolean value. For example, if you want to determine whether your catalog element contains any products whose price is less than $20, you might use the expression:

if (doc("prices.xml")//prod[price < 20])
then <bargain-bin>{local:getBargains( )}</bargain-bin>
else ( )

In this case, the result of the path expression doc("prices.xml")//prod[price < 20] is a sequence of elements that match the criteria. However, the if expression simply needs a yes/no answer regarding whether there are any elements that match the criteria. In this case, the sequence is automatically converted to its effective Boolean value, which essentially indicates whether it is empty.

Sequences are automatically interpreted as Boolean values in:

  • Conditional (if-then-else) expressions

  • Logical (and/or) expressions

  • where clauses of FLWORs

  • Quantified (some/every) expressions

  • The argument to the not function

  • The predicates of path expressions

In addition, the boolean function can be used to explicitly convert a sequence to its effective Boolean value. The effective Boolean value of a sequence is false if it is:

  • The empty sequence

  • A single, atomic value of type xs:boolean that is equal to false

  • A single, atomic value of type xs:string that is a zero-length string ("")

  • A single, atomic value with a numeric type that is equal to 0 or NaN

The effective Boolean value is undefined on a sequence of more than one item whose first item is an atomic value, and on individual atomic values whose type is not numeric, untyped, or xs:string. If the processor attempts to evaluate the effective Boolean value, and it is undefined, a type error is raised.

In all other cases, the effective Boolean value is true. This includes a sequence of one or more items whose first item is a node or a single atomic value other than those described in the preceding list. Table 11-1 shows some examples.

Table 11-1. Examples of effective Boolean value

Example

Effective Boolean value

( )

false

false( )

false

true( )

true

""

false

"false"

true

"x"

true

0

false

xs:float("NaN")

false

(false() or false( ))

false

doc("prices.xml")/*

true

<a>false</a>

true

(false(), false(), false( ))

Error

1, 2, 3

Error

xs:date("2007-01-15")

Error

Note that a node that contains a false atomic value is not the same thing as a false atomic value by itself. In the <a>false</a> example in Table 11-1, the effective Boolean value is true because a is an element node, not an atomic value of type xs:boolean. This is true even if the a element is declared to be of type xs:boolean.

Function Conversion Rules

When you call a function, sometimes the type of an argument differs from the type specified in the function signature. For example, you can pass an xs:integer to a function that expects an xs:decimal. Alternatively, you can pass an element that contains a string to a function that expects just a string. XQuery defines rules, known as function conversion rules, for converting arguments to the expected type. These function conversion rules apply only if the function expects an atomic value (or sequence of atomic values).

In fact, these function conversion rules use the various methods of type conversion and matching that are described in the preceding sections. They are put together here to show the sequential process that takes place for each argument when a function is called.

  1. Atomization is performed on the argument sequence, resulting in a sequence of atomic values.

  2. Casting of untyped values is performed. For example, the untyped value 12 can be cast to xs:integer. As noted above, typed values are not cast to other types.

  3. If the expected type is numeric or xs:string, type promotion may be performed. This means that a value of type xs:decimal can be promoted to xs:float, and xs:float can be promoted to xs:double. A value of type xs:anyURI can be promoted to xs:string.

Note that these rules do not cover converting a value to the base type from which its type is derived. For example, if an xs:unsignedInt value is passed to a function that expects an xs:integer, the value is not converted to xs:integer. However, subtype substitution does occur, and the function accepts this value.

The reverse is not true; you cannot pass an xs:integer value to a function that expects an xs:unsignedInt, even if the integer you pass meets all the tests for an xs:unsignedInt. The value must be explicitly cast to xs:unsignedInt.

As an example of the function conversion rules, if a function expects an argument of type xs:decimal?, it accepts any of the following:

  • An atomic value of type xs:decimal

  • The empty sequence, because the occurrence indicator (?) allows for it

  • An atomic value of type dty:myDecimal (derived from xs:decimal) because the sequence type xs:decimal? matches derived types as well

  • An atomic value of type xs:integer (derived from xs:decimal) because the sequence type xs:decimal? matches derived types as well

  • An atomic value of type dty:myInteger (derived from xs:integer) because the sequence type xs:decimal? matches derived types as well

  • An untyped atomic value, whose value is 12.5, because it is cast to xs:decimal (step 2)

  • An element of type xs:decimal, because its value is extracted (step 1)

  • An untyped attribute, whose value is 12, because its value is extracted (step 1) and cast to xs:decimal (step 2)

  • An untyped element whose only content is 12.5, because its value is extracted (step 1) and cast to xs:decimal (step 2)

A function expecting xs:decimal* accepts a sequence of any combination of the above items. On the other hand, a function expecting xs:decimal? does not accept:

  • An atomic value of type xs:string, even if its value is 12.5. This value must be explicitly cast to xs:decimal or a type error is raised.

  • An atomic value of type xs:float, because type promotion only works in one direction.

  • An untyped element whose only content is abc, because its value cannot be cast to xs:decimal.

  • An untyped element with no content, because its value "" (not the empty sequence) cannot be cast to xs:decimal.

  • A typed element whose type allows element-only content even if it has no children, because step 1 raises an error.

  • A sequence of multiple xs:decimal values; only one item is allowed.

Important

In XPath 1.0, if a function expects a single item and is passed a sequence of multiple items, it uses the first item and discards the rest. In XQuery 1.0/XPath 2.0, this situation raises a type error instead.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.139.83.62