XSLT 2.0 and XPath 2.0 Programmer's Reference, 4th Edition (481 page)

BOOK: XSLT 2.0 and XPath 2.0 Programmer's Reference, 4th Edition
4.94Mb size Format: txt, pdf, ePub

if (@quantity = “out-of-stock”)

     then -2

else if (@quantity = “unknown”)

     then -1

else @quantity + 2

Unfortunately, it's not as easy as that. The three places where
@quantity
is used all do atomization, which will produce either a string or an integer, but at compile time it's not known which. The
=
comparison in the condition of the
if
will fail if the value turns out to be an integer, because you can't compare an integer to a string. The
+
operator would similarly fail if the value turned out to be a string. You and I can see that this will never happen, but the XPath processor is not so clever. All it knows at compile time is that the value might be either an integer or a string.

A processor that does strict static typing will throw this out with compile time errors, because it detects that the code is unsafe (meaning, it could throw type errors at runtime). How do you get round this?

Firstly, you could try rewriting the expression like this:

if (data(@quantity) instance of xs:string)

then

    if (@quantity = “out-of-stock”)

        then -2

    else if (@quantity = “unknown”)

        then -1

    else error()

else @quantity + 2

For a system that does dynamic type checking, this is good enough. It avoids the error that would otherwise occur at runtime when you try to compare an integer to a string.

But unfortunately this still won't persuade a static type checker that all is well, because it can't follow through the logic of this code to work out that when you take one path, the value of
@quantity
must be a string, and when you take a different path, it must be an integer. So you need to use
treat
as
, like this:

if (data(@quantity) instance of xs:string) then

  if ((data(@quantity) treat as xs:string) = “out-of-stock”)

    then -2

  else if ((data(@quantity) treat as xs:string) = “unknown”))

    then -1

  else error()

else (data(@quantity) treat as xs:integer) + 2

This code will work both on systems that do strict static typing, and on those that don't. The
treat
as
operator is essentially telling the system that you know what the runtime type is going to be, and you want any checking to be deferred until runtime, because you're confident that your code is correct.

I rather suspect that few XPath 2.0 implementations will decide to implement strict static typing, so this might all turn out to be slightly irrelevant. The enthusiasm among implementors for strict static typing is far stronger in XQuery circles, where the need for optimization is so much greater. XQuery has an additional construct, the
typeswitch
expression, which makes code like that shown above much less painful to write.

Other books

Shiver and Bright by Viola Grace
The Owned Girl by Dominic Ridler
Hot Licks by Jennifer Dellerman
Amok and Other Stories by Stefan Zweig
Chicken by Chase Night
It Was Only Ever You by Kate Kerrigan
The Lost Gods by Brickley, Horace