XPath 2.0 emphasizes data types, and you can create XPath 2.0 expressions that work expressly with types using these keywords:
We'll take a look at how these expressions work now.
The instance of operator is a Boolean operator that lets you test the type of an operand. Here's how you use it in an expression, where operand2 is a simple or complex type:
operand1 instance of operand2
This expression returns true if operand1 is of the data type operand2 , and false otherwise . The type you give in operand2 can be fairly generalit can be an atomic type like xs:integer , a kind test like element() or node() , the keyword empty , or an empty sequence like this: () . It can also be the xdt:anyAtomicType type, which, as noted in Chapter 7, is an abstract type that you can't create variables of directly. If you use the xdt:anyAtomicType type with the instance of operator, you're saying that you're testing for any of the atomic types.
Using the instance of expression, you can test the data type of various items; for example, this expression returns true because 26 is an integer:
26 instance of xs:integer
Similarly, if $variable contains an integer value, this expression will return true :
$variable instance of xs:integer
TESTING xs:integer AGAINST THE xs:decimal TYPE
Actually, testing an xs:integer value against the xs:decimal type will return true because in XML schemas, the xs:integer type is derived by restriction from xs:decimal .
Here's an example that checks if 3.1415 is of type xs:decimal :
3.1415 instance of xs:decimal
Here's an example that lets you test the context item to see if it's an element:
. instance of element()
Instance of is very useful when you are working with schema- validated nodes and need to examine their runtime type.
Because XPath 2.0 implements strong typing, it's sometimes necessary to convert values from one data type to another. You can use a cast expression to change an item's data type to another data type. You can use a cast expression like this:
source cast as target-type
Here, source is cast to a new data type, the target-type . In this case, the data type of source is actually changed to the target-type , if that cast is possible.
USING CONSTRUCTOR FUNCTIONS
Bear in mind that you can also use the constructor functions that come with various types to cast data from one type to another. For example, to cast an xs:string into an xs:date , you can use the xs:date constructor function to create a new xs:date value like this: xs:date("2005-03-02") .
Here are a few examples showing how to use cast :
"2004-09-02" cast as xs:date $variable cast as xs:integer $temperature cast as xs:decimal
When can you use cast ? Here's the list:
These rules can get pretty involvedhow can you be sure the cast you're about to attempt is legal? Luckily, there's a fairly easy answer to thatyou can use a castable expression to check if a cast is legal.
The castable expression lets you test if an item may be cast to a specific type, and it returns a true / false answer. Here's how you use this expression:
source castable as target-type
This expression is true if source may be cast to target-type . Here's an example where we're checking whether $fruit may be cast to the type apple , and if not, whether it can be cast to the type orange :
if ($fruit castable as apple) then $fruit cast as apple else if ($fruit castable as orange) then $fruit cast as orange else $fruit cast as xs:string
The treat expression is much like the cast expression, except that, unlike cast , it doesn't change the type of its operand. It acts like an assertion, checking the type of an expression. Here's how you use the treat operator in an expression:
source treat as target-type
This expression asserts that source is of the target-type data type. Otherwise, this expression returns an error.
Here's an example. In this case, the original type of $number might be number . Say that another type, ZIP , is derived from that type; in that case, this expression will be of the ZIP type when evaluated:
$number treat as ZIP
This expression also succeeds if the type of $number is ZIP . In other words, the treat expression acts much like an assertion, which succeeds if $number is of type ZIP or of a type derived from ZIP .