Start of change

Castable expressions

Castable expressions test whether a value can be cast to a specific data type. If the value can be cast to the data type, the castable expression returns true. Otherwise, the expression returns false.

Castable expressions can be used as predicates to avoid cast errors at evaluation time. They can also be used to select an appropriate type for processing a value.

Syntax

Read syntax diagram
>>-expression--castable as--target-type--+---+-----------------><
                                         '-?-'   

expression
An XQuery expression that returns a single atomic value or an empty sequence.
target-type
The type used to test if the value of expression can be cast. target-type must be an atomic type that is one of the predefined XML schema types. The data types xs:anyAtomicType and xs:anySimpleType are not valid types for target-type.
?
Indicates that an empty sequence is considered to be a valid instance of the target type. If expression evaluates to an empty sequence and ? is not specified, the castable expression returns false.

Returned value

If expression can be cast to target-type, the castable expression returns true. Otherwise, the expression returns false.

If the result of expression is an empty sequence, and the question mark indicator follows target-type, the castable expression returns true. In the following example, the question mark indicator follows the target type xs:integer.

$prod/revision castable as xs:integer?
An error is returned in the following cases:
  • The result of expression is a sequence of more than one atomic value.
  • target-type is not an atomic data type that is defined for the in-scope XML schema types or is a data type that cannot be used in a castable expression.

Examples

The following example uses a castable expression as a predicate to avoid errors at evaluation time. The example avoids a dynamic error if @OrderDate is not a valid date.

Start of change
let $i := if ( $po/@OrderDate castable as xs:date)
              then xs:date($po/@OrderDate) gt xs:date("2009-01-01")
              else 0
return  $po/orderID[$i]
End of change

The predicate is true and returns the orderID only if the date attribute is a valid date greater than January 1, 2009. Otherwise, the predicate is false and returns an empty sequence.

The following example uses a castable expression to select an appropriate type for processing of a given value. The example casts a postal code as either an integer or a string.

Start of change
if ($postalcode castable as xs:integer)
   then xs:integer($postalcode)
   else xs:string($postalcode)
End of change

The following example uses a castable expression in the FLWOR let clause to test the value of $prod/mfgdate and bind a value to $currdate. The castable expression supports processing an empty sequence using the question mark indicator.

Start of change
let $currdate := if ($prod/mfgdate castable as xs:date?)
   then xs:date($prod/mfgdate)
   else xs:date("2000-01-01")
End of change

If the value of $prod/mfgdate can be cast as xs:date, it is cast to the data type and is bound to $currdate. If $prod/mfgdate is an empty sequence, an empty sequence is bound to $currdate. If $prod/mfgdate cannot be cast as xs:date, a value of 2000-01-01 of type xs:date is bound to $currdate.

In the following example, the castable expression in the XMLEXISTS predicate tests the value of /prod/category before performing a comparison to avoid errors at evaluation time. In the XML column FEATURES.INFO, the documents contain the element /prod/category. The value is either a numeric code or string code.

SELECT F.PRODID FROM F FEATURES
  WHERE XMLEXISTS('$test/prod/category[ (( . castable as xs:double) and . > 100 ) or
  (( . castable as xs:string) and . > "A100" )]'
  PASSING F.INFO as "test")

The returned values are product IDs where the category codes are either greater than the number 100 or greater than the string "A100".

End of change