Constructor functions and cast expressions accept an expression and return a value
of a given type. They both convert a source value, SV, of a source type,
ST, to a target value, TV, of the given target type,
TT, with identical semantics and different syntax. The name of the
constructor function is the same as the name of the built-in [XML Schema Part 2: Datatypes Second Edition]
datatype or the datatype defined in Section
2.7 Schema Information
DM31
of [XQuery and XPath Data Model (XDM) 3.1] (see 18.1 Constructor functions for XML Schema built-in atomic types) or the user-derived datatype
(see 18.5 Constructor functions for user-defined types) that is the
target for the conversion, and the semantics are exactly the same as for a cast
expression; for example,
xs:date("2003-01-01")
means exactly the same as
"2003-01-01"
cast as xs:date?
.
The cast expression takes a type name to indicate the target type of the conversion. See Section 3.14.2 Cast XP31. If the type name allows the empty sequence and the expression to be cast is the empty sequence, the empty sequence is returned. If the type name does not allow the empty sequence and the expression to be cast is the empty sequence, a type error is raised [err:XPTY0004]XP.
Where the argument to a cast is a literal, the result of the function may be evaluated statically; if an error is encountered during such evaluation, it may be reported as a static error.
The general rules for casting from primitive types to primitive types are defined in
19.1 Casting from primitive types to primitive types, and subsections describe the rules
for specific target types.
The general rules for casting from xs:string
(and xs:untypedAtomic
)
follow in 19.2 Casting from xs:string and xs:untypedAtomic.
Casting to non-primitive types, including atomic types derived by resctriction,
union types, and list types, is described in 19.3 Casting involving non-primitive types.
Casting from derived types is defined in 19.3.2 Casting from derived types to parent types,
19.3.3 Casting within a branch of the type hierarchy and 19.3.4 Casting across the type hierarchy.
[Definition] Throughout
this section (19 Casting), the term primitive type means either one of
the 19 primitive types defined in [XML Schema Part 2: Datatypes Second Edition], or one of the types
xs:untypedAtomic
, xs:integer
, xs:yearMonthDuration
and xs:dayTimeDuration
; and where the text refers to types derived from a particular
primitive type T, the reference is to types for which T is the nearest
ancestor-or-self primitive type in the type hierarchy.
When casting from xs:string
or xs:untypedAtomic
the semantics in 19.2 Casting from xs:string and xs:untypedAtomic apply, regardless of target type.
This section defines casting between ·primitive types·
(specifically, the 19 primitive types defined in [XML Schema Part 2: Datatypes Second Edition] as well as xs:untypedAtomic
,
xs:integer
and the two derived types of
xs:duration
: xs:yearMonthDuration
and xs:dayTimeDuration
which are treated as primitive types in this section. The type conversions
that are supported between primitive atomic types are indicated in the table below;
casts between other (non-primitive) types are defined in terms of these primitives.
In this table, there is a
row for each ·primitive type· acting as the source of the conversion and
there is a column for each ·primitive type· acting as the target of the conversion. The
intersections of rows and columns contain one of three characters:
Y
indicates that a conversion from values of the type to which
the row applies to the type to which the column applies is supported;
N
indicates that there are no supported conversions from values
of the type to which the row applies to the type to which the column applies;
and M
indicates that a conversion from values of the type to
which the row applies to the type to which the column applies may succeed for
some values in the value space and fail for others.
[XML Schema Part 2: Datatypes Second Edition] defines xs:NOTATION
as an abstract type.
Thus, casting to xs:NOTATION
from any other type including xs:NOTATION
is not permitted and raises a static error [err:XPST0080]XP.
However, casting from one subtype of xs:NOTATION
to another subtype of
xs:NOTATION
is permitted.
Casting is not supported to or from xs:anySimpleType
. Thus, there is no row
or column for this type in the table below. For any node that has not been validated or
has been validated as xs:anySimpleType
, the typed value of the node is an
atomic value of type xs:untypedAtomic
. There are no atomic values with the
type annotation xs:anySimpleType
at runtime.
Casting to
xs:anySimpleType
is not permitted and raises a static error:
[err:XPST0080]XP.
Similarly, casting is not supported to or from xs:anyAtomicType
and will raise
a static error: [err:XPST0080]XP. There are no atomic values
with the type annotation xs:anyAtomicType
at runtime, although this can be a
statically inferred type.
If casting is attempted from an ST to a TT for which casting is not supported, as defined in the table below, a type error is raised [err:XPTY0004]XP.
In the following table, the columns and rows are identified by short codes that identify simple types as follows:
uA = xs:untypedAtomic
aURI = xs:anyURI
b64 = xs:base64Binary
bool = xs:boolean
dat = xs:date
gDay = xs:gDay
dbl = xs:double
dec = xs:decimal
dT = xs:dateTime
dTD = xs:dayTimeDuration
dur = xs:duration
flt = xs:float
hxB = xs:hexBinary
gMD = xs:gMonthDay
gMon = xs:gMonth
int = xs:integer
NOT = xs:NOTATION
QN = xs:QName
str = xs:string
tim = xs:time
gYM = xs:gYearMonth
yMD = xs:yearMonthDuration
gYr = xs:gYear
In the following table, the notation "S\T" indicates that the source ("S") of the conversion is indicated in the column below the notation and that the target ("T") is indicated in the row to the right of the notation.
S\T | uA | str | flt | dbl | dec | int | dur | yMD | dTD | dT | tim | dat | gYM | gYr | gMD | gDay | gMon | bool | b64 | hxB | aURI | QN | NOT |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
uA | Y | Y | M | M | M | M | M | M | M | M | M | M | M | M | M | M | M | M | M | M | M | M | M |
str | Y | Y | M | M | M | M | M | M | M | M | M | M | M | M | M | M | M | M | M | M | M | M | M |
flt | Y | Y | Y | Y | M | M | N | N | N | N | N | N | N | N | N | N | N | Y | N | N | N | N | N |
dbl | Y | Y | Y | Y | M | M | N | N | N | N | N | N | N | N | N | N | N | Y | N | N | N | N | N |
dec | Y | Y | Y | Y | Y | Y | N | N | N | N | N | N | N | N | N | N | N | Y | N | N | N | N | N |
int | Y | Y | Y | Y | Y | Y | N | N | N | N | N | N | N | N | N | N | N | Y | N | N | N | N | N |
dur | Y | Y | N | N | N | N | Y | Y | Y | N | N | N | N | N | N | N | N | N | N | N | N | N | N |
yMD | Y | Y | N | N | N | N | Y | Y | Y | N | N | N | N | N | N | N | N | N | N | N | N | N | N |
dTD | Y | Y | N | N | N | N | Y | Y | Y | N | N | N | N | N | N | N | N | N | N | N | N | N | N |
dT | Y | Y | N | N | N | N | N | N | N | Y | Y | Y | Y | Y | Y | Y | Y | N | N | N | N | N | N |
tim | Y | Y | N | N | N | N | N | N | N | N | Y | N | N | N | N | N | N | N | N | N | N | N | N |
dat | Y | Y | N | N | N | N | N | N | N | Y | N | Y | Y | Y | Y | Y | Y | N | N | N | N | N | N |
gYM | Y | Y | N | N | N | N | N | N | N | N | N | N | Y | N | N | N | N | N | N | N | N | N | N |
gYr | Y | Y | N | N | N | N | N | N | N | N | N | N | N | Y | N | N | N | N | N | N | N | N | N |
gMD | Y | Y | N | N | N | N | N | N | N | N | N | N | N | N | Y | N | N | N | N | N | N | N | N |
gDay | Y | Y | N | N | N | N | N | N | N | N | N | N | N | N | N | Y | N | N | N | N | N | N | N |
gMon | Y | Y | N | N | N | N | N | N | N | N | N | N | N | N | N | N | Y | N | N | N | N | N | N |
bool | Y | Y | Y | Y | Y | Y | N | N | N | N | N | N | N | N | N | N | N | Y | N | N | N | N | N |
b64 | Y | Y | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | Y | Y | N | N | N |
hxB | Y | Y | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | Y | Y | N | N | N |
aURI | Y | Y | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | Y | N | N |
QN | Y | Y | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | Y | M |
NOT | Y | Y | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | Y | M |
Casting is permitted from any ·primitive type· to the
·primitive types·
xs:string
and xs:untypedAtomic
.
When a value of any simple type is cast as xs:string
, the
derivation of the xs:string
value TV depends on
the ST and on the SV, as follows.
If ST is xs:string
or a type derived from
xs:string
, TV is SV.
If ST is xs:anyURI
, the type conversion is
performed without escaping any characters.
If ST is xs:QName
or xs:NOTATION
:
if the qualified name has a prefix, then TV is the concatenation of the prefix of SV, a single colon (:), and the local name of SV.
otherwise TV is the local-name.
If ST is a numeric type, the following rules apply:
If ST is xs:integer
,
TV is the canonical lexical representation of
SV as defined in [XML Schema Part 2: Datatypes Second Edition]. There
is no decimal point.
If ST is xs:decimal
, then:
If SV is in the value space of
xs:integer
, that is, if there are no
significant digits after the decimal point, then the
value is converted from an xs:decimal
to an xs:integer
and the resulting
xs:integer
is converted to an
xs:string
using the rule above.
Otherwise, the canonical lexical representation of SV is returned, as defined in [XML Schema Part 2: Datatypes Second Edition].
If ST is xs:float
or
xs:double
, then:
TV will be an xs:string
in the lexical space of xs:double
or xs:float
that when
converted to an xs:double
or xs:float
under the rules of 19.2 Casting from xs:string and xs:untypedAtomic produces
a value that is equal to SV, or is NaN
if SV is NaN
.
In addition, TV must satisfy the constraints in the
following sub-bullets.
If SV has an absolute value that is
greater than or equal to 0.000001 (one millionth)
and less than 1000000 (one million), then the value
is converted to an xs:decimal
and the
resulting xs:decimal
is converted to an
xs:string
according to the rules above, as though using an
implementation of xs:decimal
that imposes no limits on the
totalDigits
or
fractionDigits
facets.
If SV has the value positive or negative zero, TV is "0" or "-0" respectively.
If SV is positive or negative infinity, TV is the string "INF
" or "-INF
" respectively.
In other cases, the result consists of a mantissa, which has the lexical form
of an xs:decimal
, followed by the letter "E", followed by an exponent which has
the lexical form of an xs:integer
. Leading zeroes and "+" signs are prohibited
in the exponent. For the mantissa, there must be a decimal point, and there must
be exactly one digit before the decimal point, which must be non-zero. The "+"
sign is prohibited. There must be at least one digit after the decimal point.
Apart from this mandatory digit, trailing zero digits are prohibited.
Note:
The above rules allow more than one representation of the same value.
For example, the xs:float
value whose exact decimal representation is 1.26743223E15
might be represented by any of the strings "1.26743223E15", "1.26743222E15" or
"1.26743224E15" (inter alia). It is implementation-dependent which of these
representations is chosen.
If ST is xs:dateTime
, xs:date
or xs:time
, TV is the local value.
The components of TV are individually cast to xs:string
using the functions
described in [casting-to-datetimes]
and the results are concatenated together. The year
component is
cast to xs:string
using eg:convertYearToString
.
The month
, day
, hour
and minute
components are cast to xs:string
using eg:convertTo2CharString
.
The second
component is cast to xs:string
using
eg:convertSecondsToString
. The timezone component, if present, is
cast to xs:string
using eg:convertTZtoString
.
Note that the hours component of the resulting string
will never be "24"
. Midnight is always represented as "00:00:00"
.
If ST is xs:yearMonthDuration
or xs:dayTimeDuration
, TV is the
canonical representation of SV as defined in [Schema 1.1 Part 2].
If ST is xs:duration
then let SYM be
SV
cast as xs:yearMonthDuration
, and let SDT be
SV
cast as xs:dayTimeDuration
; Now, let the next intermediate value, TYM,
be
SYM
cast as
TT
, and let TDT be
SDT
cast as
TT
. If TYM is "P0M", then TV is
TDT. Otherwise, TYM and TDT are merged according to the following rules:
If TDT is "PT0S", then TV is TYM.
Otherwise, TV is the concatenation of all the characters in TYM and all the characters except the first "P" and the optional negative sign in TDT.
In all other cases, TV is the [XML Schema Part 2: Datatypes Second Edition] canonical representation of SV. For datatypes that do not have a canonical lexical representation defined an ·implementation-dependent· canonical representation may be used.
To cast as xs:untypedAtomic
the value is cast as
xs:string
, as described above, and the type annotation changed
to xs:untypedAtomic
.
Note:
The string representations of numeric values are backwards compatible
with XPath 1.0 except for the special values positive and negative
infinity, negative zero and values outside the range 1.0e-6
to 1.0e+6
.
When a value of any simple type is cast as xs:float
, the xs:float
TV is derived from the ST and the
SV as follows:
If ST is xs:float
, then TV
is SV and the conversion is complete.
If ST is xs:double
, then
TV is obtained as follows:
if SV is the xs:double
value
INF
, -INF
, NaN
,
positive zero, or negative zero, then TV is
the xs:float
value INF
,
-INF
, NaN
, positive zero, or
negative zero respectively.
otherwise, SV can be expressed in the form
m × 2^e
where the mantissa
m
and exponent e
are signed
xs:integer
s whose value range is defined in
[XML Schema Part 2: Datatypes Second Edition], and the following rules apply:
if m
(the mantissa of
SV) is outside the permitted range
for the mantissa of an xs:float
value (-2^24-1 to +2^24-1)
, then it
is divided by 2^N
where
N
is the lowest positive
xs:integer
that brings the result
of the division within the permitted range, and
the exponent e
is increased by
N
. This is integer division (in
effect, the binary value of the mantissa is
truncated on the right). Let M
be
the mantissa and E
the exponent
after this adjustment.
if E
exceeds 104
(the
maximum exponent value in the value space of
xs:float
) then TV is
the xs:float
value INF
or -INF
depending on the sign of M
.
if E
is less than -149
(the minimum exponent value in the value space
of xs:float
) then TV is
the xs:float
value positive or
negative zero depending on the sign of M
otherwise, TV is the
xs:float
value M × 2^E
.
If ST is xs:decimal
, or
xs:integer
, then TV is xs:float(
SV
cast as xs:string)
and the conversion is complete.
If ST is xs:boolean
, SV is
converted to 1.0E0
if SV is
true
and to 0.0E0
if SV
is false
and the conversion is complete.
If ST is xs:untypedAtomic
or xs:string
, see
19.2 Casting from xs:string and xs:untypedAtomic.
Note:
XSD 1.1 adds the value +INF
to the lexical space,
as an alternative to INF
. XSD 1.1 also adds negative zero
to the value space.
Note:
Implementations should return negative zero for xs:float("-0.0E0")
.
But because [XML Schema Part 2: Datatypes Second Edition] does not distinguish between the values positive zero and negative zero.
Implementations may return positive zero in this case.
When a value of any simple type is cast as xs:double
, the
xs:double
value TV is derived from the
ST and the SV as follows:
If ST is xs:double
, then
TV is SV and the conversion is complete.
If ST is xs:float
or a type derived
from xs:float
, then TV is obtained as follows:
if SV is the xs:float
value
INF
, -INF
, NaN
,
positive zero, or negative zero, then TV is
the xs:double
value INF
,
-INF
, NaN
, positive zero, or
negative zero respectively.
otherwise, SV can be expressed in the form
m × 2^e
where the
mantissa m
and exponent e
are
signed xs:integer
values whose value range
is defined in [XML Schema Part 2: Datatypes Second Edition], and
TV is the xs:double
value
m × 2^e
.
If ST is xs:decimal
or
xs:integer
, then TV is xs:double(
SV
cast as xs:string)
and the conversion is complete.
If ST is xs:boolean
, SV is
converted to 1.0E0
if SV is
true
and to 0.0E0
if SV
is false
and the conversion is complete.
If ST is xs:untypedAtomic
or xs:string
, see
19.2 Casting from xs:string and xs:untypedAtomic.
Note:
XSD 1.1 adds the value +INF
to the lexical space,
as an alternative to INF
. XSD 1.1 also adds negative zero
to the value space.
Note:
Implementations should return negative zero for xs:double("-0.0E0")
.
But because [XML Schema Part 2: Datatypes Second Edition] does not distinguish between the values positive zero and negative zero.
Implementations may return positive zero in this case.
When a value of any simple type is cast as xs:decimal
, the
xs:decimal
value TV is derived from
ST and SV as follows:
If ST is xs:decimal
,
xs:integer
or a type derived from them, then
TV is SV, converted to an
xs:decimal
value if need be, and the conversion is complete.
If ST is xs:float
or
xs:double
, then TV is the
xs:decimal
value, within the set of
xs:decimal
values that the implementation is
capable of representing, that is numerically closest to
SV. If two values are equally close, then the one
that is closest to zero is chosen. If SV is too
large to be accommodated as an xs:decimal
, (see
[XML Schema Part 2: Datatypes Second Edition] for ·implementation-defined· limits on
numeric values) a dynamic error is raised [err:FOCA0001]. If SV is one of the special
xs:float
or xs:double
values
NaN
, INF
, or -INF
, a dynamic
error is raised [err:FOCA0002].
If ST is xs:boolean
, SV is
converted to 1.0
if SV is
1
or true
and to 0.0
if
SV is 0
or false
and the
conversion is complete.
If ST is xs:untypedAtomic
or xs:string
, see
19.2 Casting from xs:string and xs:untypedAtomic.
When a value of any simple type is cast as xs:integer
, the
xs:integer
value TV is derived from
ST and SV as follows:
If ST is xs:integer
, or a type derived
from xs:integer
, then TV is
SV, converted to an xs:integer
value
if need be, and the conversion is complete.
If ST is
xs:decimal
, xs:float
or
xs:double
, then TV is SV
with the fractional part discarded and the value converted to
xs:integer
. Thus, casting 3.1456
returns 3
and -17.89
returns
-17
. Casting 3.124E1
returns 31
. If SV is too large to be
accommodated as an integer, (see [XML Schema Part 2: Datatypes Second Edition] for
·implementation-defined· limits on numeric values) a
dynamic error is
raised [err:FOCA0003]. If SV is
one of the special xs:float
or
xs:double
values NaN
,
INF
, or -INF
, a dynamic error is raised
[err:FOCA0002].
If ST is xs:boolean
, SV is
converted to 1
if SV is 1
or true
and to 0
if SV is
0
or false
and the conversion is complete.
If ST is xs:untypedAtomic
or xs:string
, see
19.2 Casting from xs:string and xs:untypedAtomic.
When a value of type xs:untypedAtomic
, xs:string
,
a type derived from xs:string
,
xs:yearMonthDuration
or xs:dayTimeDuration
is
cast as xs:duration
, xs:yearMonthDuration
or
xs:dayTimeDuration
, TV is derived from
ST and SV as follows:
If ST is the same as TT, then TV is SV.
If ST is xs:duration
, or a type derived
from xs:duration
, but not
xs:dayTimeDuration
or a type derived from
xs:dayTimeDuration
, and TT is
xs:yearMonthDuration
, then TV is derived
from SV by removing the day, hour, minute and second
components from SV.
If ST is xs:duration
, or a type derived
from duration
, but not
xs:yearMonthDuration
or a type derived from
xs:yearMonthDuration
, and TT is
xs:dayTimeDuration
, then TV is derived
from SV by removing the year and month components from SV.
If ST is xs:yearMonthDuration
or xs:dayTimeDuration
, and TT is
xs:duration
, then TV is derived from
SV as defined in 19.3.2 Casting from derived types to parent types.
If ST is xs:yearMonthDuration
and TT is
xs:dayTimeDuration
, the cast is permitted and returns a xs:dayTimeDuration
with value 0.0 seconds.
If ST is xs:dayTimeDuration
and TT is
xs:yearMonthDuration
, the cast is permitted and returns a xs:yearMonthDuration
with value 0 months.
If ST is xs:untypedAtomic
or xs:string
, see
19.2 Casting from xs:string and xs:untypedAtomic.
Note that casting from xs:duration
to
xs:yearMonthDuration
or xs:dayTimeDuration
loses
information. To avoid this, users can cast the xs:duration
value to both an xs:yearMonthDuration
and an
xs:dayTimeDuration
and work with both values.
In several situations, casting to date and time types requires the extraction
of a component from SV or from the result of
fn:current-dateTime
and converting it to an
xs:string
. These conversions must follow certain rules. For
example, converting an xs:integer
year value requires
converting to an xs:string
with four or more characters, preceded
by a minus sign if the value is negative.
This document defines four functions to perform these conversions. These functions are for illustrative purposes only and make no recommendations as to style or efficiency. References to these functions from the following text are not normative.
The arguments to these functions come from functions defined in this document. Thus, the functions below assume that they are correct and do no range checking on them.
declare function eg:convertYearToString($year as xs:integer) as xs:string { let $plusMinus := if ($year >= 0) then "" else "-" let $yearString := fn:abs($year) cast as xs:string let $length := fn:string-length($yearString) return if ($length = 1) then fn:concat($plusMinus, "000", $yearString) else if ($length = 2) then fn:concat($plusMinus, "00", $yearString) else if ($length = 3) then fn:concat($plusMinus, "0", $yearString) else fn:concat($plusMinus, $yearString) }
declare function eg:convertTo2CharString($value as xs:integer) as xs:string { let $string := $value cast as xs:string return if (fn:string-length($string) = 1) then fn:concat("0", $string) else $string }
declare function eg:convertSecondsToString($seconds as xs:decimal) as xs:string { let $string := $seconds cast as xs:string let $intLength := fn:string-length(($seconds cast as xs:integer) cast as xs:string) return if ($intLength = 1) then fn:concat("0", $string) else $string }
declare function eg:convertTZtoString($tz as xs:dayTimeDuration?) as xs:string { if (empty($tz)) then "" else if ($tz eq xs:dayTimeDuration('PT0S')) then "Z" else let $tzh := fn:hours-from-duration($tz) let $tzm := fn:minutes-from-duration($tz) let $plusMinus := if ($tzh >= 0) then "+" else "-" let $tzhString := eg:convertTo2CharString(fn:abs($tzh)) let $tzmString := eg:convertTo2CharString(fn:abs($tzm)) return fn:concat($plusMinus, $tzhString, ":", $tzmString) }
Conversion from ·primitive types· to date and time types follows the rules below.
When a value of any primitive type is cast as
xs:dateTime
, the xs:dateTime
value
TV is derived from ST and SV
as follows:
If ST is xs:dateTime
, then
TV is SV.
If ST is xs:date
, then let
SYR be eg:convertYearToString( fn:year-from-date(
SV
))
, let SMO be
eg:convertTo2CharString( fn:month-from-date(
SV
))
, let SDA be
eg:convertTo2CharString( fn:day-from-date(
SV
))
and let STZ be
eg:convertTZtoString( fn:timezone-from-date(
SV
))
; TV is xs:dateTime( fn:concat(
SYR
, '-',
SMO
, '-',
SDA
, 'T00:00:00 '
, STZ
) )
.
If ST is xs:untypedAtomic
or
xs:string
, see
19.2 Casting from xs:string and xs:untypedAtomic.
When a value of any primitive type is cast as xs:time
,
the xs:time
value TV is derived from
ST and SV as follows:
If ST is xs:time
, then
TV is SV.
If ST is xs:dateTime
, then
TV is xs:time( fn:concat(
eg:convertTo2CharString( fn:hours-from-dateTime(
SV
)), ':', eg:convertTo2CharString( fn:minutes-from-dateTime(
SV
)), ':', eg:convertSecondsToString( fn:seconds-from-dateTime(
SV
)), eg:convertTZtoString( fn:timezone-from-dateTime(
SV
)) ))
.
If ST is xs:untypedAtomic
or xs:string
, see
19.2 Casting from xs:string and xs:untypedAtomic.
When a value of any primitive type is cast as xs:date
,
the xs:date
value TV is derived from
ST and SV as follows:
If ST is xs:date
, then
TV is SV.
If ST is xs:dateTime
, then let
SYR be eg:convertYearToString( fn:year-from-dateTime(
SV
))
, let SMO be
eg:convertTo2CharString( fn:month-from-dateTime(
SV
))
, let SDA be
eg:convertTo2CharString( fn:day-from-dateTime(
SV
))
and let STZ be eg:convertTZtoString(fn:timezone-from-dateTime(
SV
))
; TV is xs:date( fn:concat(
SYR
, '-',
SMO
, '-',
SDA, STZ
) )
.
If ST is xs:untypedAtomic
or xs:string
, see
19.2 Casting from xs:string and xs:untypedAtomic.
When a value of any primitive type is cast as
xs:gYearMonth
, the xs:gYearMonth
value
TV is derived from ST and SV
as follows:
If ST is xs:gYearMonth
, then
TV is SV.
If ST is xs:dateTime
, then let
SYR be eg:convertYearToString( fn:year-from-dateTime(
SV
))
, let SMO be
eg:convertTo2CharString( fn:month-from-dateTime(
SV
))
and let STZ be
eg:convertTZtoString( fn:timezone-from-dateTime(
SV
))
; TV is xs:gYearMonth( fn:concat(
SYR
, '-',
SMO, STZ
) )
.
If ST is xs:date
, then let
SYR be eg:convertYearToString( fn:year-from-date(
SV
))
, let SMO be
eg:convertTo2CharString( fn:month-from-date(
SV
))
and let STZ be
eg:convertTZtoString( fn:timezone-from-date(
SV
))
; TV is xs:gYearMonth( fn:concat(
SYR
, '-',
SMO, STZ
) )
.
If ST is xs:untypedAtomic
or xs:string
, see
19.2 Casting from xs:string and xs:untypedAtomic.
When a value of any primitive type is cast as xs:gYear
,
the xs:gYear
value TV is derived from
ST and SV as follows:
If ST is xs:gYear
, then
TV is SV.
If ST is xs:dateTime
, let
SYR be eg:convertYearToString( fn:year-from-dateTime(
SV
))
and let STZ be
eg:convertTZtoString( fn:timezone-from-dateTime(
SV
))
; TV is xs:gYear(fn:concat(
SYR, STZ
))
.
If ST is xs:date
, let
SYR be eg:convertYearToString( fn:year-from-date(
SV
))
; and let STZ be
eg:convertTZtoString( fn:timezone-from-date(
SV
))
; TV is xs:gYear(fn:concat(
SYR, STZ
))
.
If ST is xs:untypedAtomic
or xs:string
, see
19.2 Casting from xs:string and xs:untypedAtomic.
When a value of any primitive type is cast as
xs:gMonthDay
, the xs:gMonthDay
value
TV is derived from ST and SV
as follows:
If ST is xs:gMonthDay
, then
TV is SV.
If ST is xs:dateTime
, then let
SMO be eg:convertTo2CharString( fn:month-from-dateTime(
SV
))
, let SDA be
eg:convertTo2CharString( fn:day-from-dateTime(
SV
))
and let STZ be
eg:convertTZtoString( fn:timezone-from-dateTime(
SV
))
; TV is xs:gYearMonth( fn:concat(
'--',
SMO
'-',
SDA, STZ
) )
.
If ST is xs:date
, then let
SMO be eg:convertTo2CharString( fn:month-from-date(
SV
))
, let SDA be
eg:convertTo2CharString( fn:day-from-date(
SV
))
and let STZ be
eg:convertTZtoString( fn:timezone-from-date(
SV
))
; TV is xs:gYearMonth( fn:concat(
'--',
SMO
, '-',
SDA, STZ
) )
.
If ST is xs:untypedAtomic
or xs:string
, see
19.2 Casting from xs:string and xs:untypedAtomic.
When a value of any primitive type is cast as xs:gDay
,
the xs:gDay
value TV is derived from
ST and SV as follows:
If ST is xs:gDay
, then
TV is SV.
If ST is xs:dateTime
, then let
SDA be eg:convertTo2CharString( fn:day-from-dateTime(
SV
))
and let STZ be
eg:convertTZtoString( fn:timezone-from-dateTime(
SV
))
; TV is xs:gDay(
fn:concat( '---'
, SDA, STZ
))
.
If ST is xs:date
, then let
SDA be eg:convertTo2CharString( fn:day-from-date(
SV
))
and let STZ be
eg:convertTZtoString( fn:timezone-from-date(
SV
))
; TV is xs:gDay(
fn:concat( '---'
, SDA, STZ
))
.
If ST is xs:untypedAtomic
or xs:string
, see
19.2 Casting from xs:string and xs:untypedAtomic.
When a value of any primitive type is cast as xs:gMonth
,
the xs:gMonth
value TV is derived from
ST and SV as follows:
If ST is xs:gMonth
, then
TV is SV.
If ST is xs:dateTime
, then let
SMO be eg:convertTo2CharString( fn:month-from-dateTime(
SV
))
and let STZ be
eg:convertTZtoString( fn:timezone-from-dateTime(
SV
))
; TV is xs:gMonth(
fn:concat( '--'
, SMO, STZ
))
.
If ST is xs:date
, then let
SMO be eg:convertTo2CharString( fn:month-from-date(
SV
))
and let STZ be
eg:convertTZtoString( fn:timezone-from-date(
SV
))
; TV is xs:gMonth(
fn:concat( '--'
, SMO, STZ
))
.
If ST is xs:untypedAtomic
or xs:string
, see
19.2 Casting from xs:string and xs:untypedAtomic.
When a value of any ·primitive type· is cast as xs:boolean
, the
xs:boolean
value TV is derived from
ST and SV as follows:
If ST is xs:boolean
, then TV
is SV.
If ST is xs:float
, xs:double
,
xs:decimal
or xs:integer
and
SV is 0
, +0
, -0
,
0.0
, 0.0E0
or NaN
, then
TV is false
.
If ST is xs:float
, xs:double
,
xs:decimal
or xs:integer
and
SV is not one of the above values, then TV
is true
.
If ST is xs:untypedAtomic
or xs:string
, see
19.2 Casting from xs:string and xs:untypedAtomic.
Values of type xs:base64Binary
can be cast as
xs:hexBinary
and vice versa, since the two types have the same
value space. Casting to xs:base64Binary
and
xs:hexBinary
is also supported from the same type and from
xs:untypedAtomic
, xs:string
and subtypes of
xs:string
using [XML Schema Part 2: Datatypes Second Edition] semantics.
Casting to xs:anyURI
is supported only from the same type,
xs:untypedAtomic
or xs:string
.
When a value of any ·primitive type· is cast as xs:anyURI
, the
xs:anyURI
value TV is derived from the
ST and SV as follows:
If ST is xs:untypedAtomic
or xs:string
see
19.2 Casting from xs:string and xs:untypedAtomic.
Casting from xs:string
or xs:untypedAtomic
to
xs:QName
or xs:NOTATION
is described in
19.2 Casting from xs:string and xs:untypedAtomic.
It is also possible to cast from xs:NOTATION
to xs:QName
,
or from xs:QName
to
any type derived by restriction from xs:NOTATION
. (Casting to xs:NOTATION
itself is not allowed, because xs:NOTATION
is an abstract type.) The resulting
xs:QName
or xs:NOTATION
has the same prefix, local name, and namespace URI
parts as the supplied value.
Note:
See 18.2 Constructor functions for xs:QName and xs:NOTATION for a discussion of how the combination of atomization and casting might not produce the desired effect.
[XML Schema Part 2: Datatypes Second Edition] says that "The
value space of ENTITY is the set of all strings that match the
NCName production ... and have been
declared as an unparsed entity in a document type definition."
However,
[XSL Transformations (XSLT) Version 4.0] and [XQuery 4.1: An XML Query Language] do not check that constructed values of type xs:ENTITY
match declared unparsed entities. Thus, this rule is relaxed in this specification and, in casting to xs:ENTITY
and types derived from it, no check is made that the values correspond to declared unparsed entities.
This section applies when the supplied value SV
is an instance of xs:string
or xs:untypedAtomic
,
including types derived from these by restriction. If the value is
xs:untypedAtomic
, it is treated in exactly the same way as a
string containing the same sequence of characters.
The supplied string is mapped to a typed value of the target type as defined in [XML Schema Part 2: Datatypes Second Edition].
Whitespace normalization is applied as indicated by the
whiteSpace
facet for the datatype. The resulting whitespace-normalized string
must be a valid lexical form for the datatype. The semantics of casting follow the rules of
XML Schema validation. For example, "13" cast as xs:unsignedInt
returns
the xs:unsignedInt
typed
value 13
. This could also be written xs:unsignedInt("13")
.
The target type can be any simple type other than an abstract type. Specifically, it can be a type whose variety is atomic, union, or list. In each case the effect of casting to the target type is the same as constructing an element with the supplied value as its content, validating the element using the target type as the governing type, and atomizing the element to obtain its typed value.
When the target type is a derived type that is restricted by a pattern facet, the lexical form is first checked against the pattern before further casting is attempted (See 19.3.1 Casting to derived types). If the lexical form does not conform to the pattern, a dynamic error [err:FORG0001] is raised.
For example, consider a user-defined type my:boolean
which is derived by
restriction from xs:boolean
and specifies the pattern facet value="0|1"
.
The expression "true" cast as my:boolean
would fail with a dynamic
error [err:FORG0001].
Facets other than pattern
are checked after the conversion.
For example if there is a user-defined datatype called my:height
defined as a restriction of xs:integer
with the facet <maxInclusive value="84"/>
,
then the expression "100" cast as my:height
would fail with a dynamic
error [err:FORG0001].
Casting to the types xs:NOTATION
, xs:anySimpleType
,
or xs:anyAtomicType
is not permitted because these types are abstract (they have
no immediate instances).
Special rules apply when casting to namespace-sensitive types. The types xs:QName
and xs:NOTATION
are namespace-sensitive. Any type derived by restriction from
a namespace-sensitive type is itself namespace-sensitive, as is any union type having a
namespace-sensitive type among its members, and any list type having a namespace-sensitive type
as its item type. For details, see 18.2 Constructor functions for xs:QName and xs:NOTATION.
Note:
This version of the specification allows casting between xs:QName
and xs:NOTATION
in either direction; this was not permitted in the previous Recommendation. This version also removes
the rule that only a string literal (rather than a dynamic string) may be cast to an xs:QName
When casting to a numeric type:
If the value is too large or too small to be accurately represented by the implementation, it is handled as an overflow or underflow as defined in 4.2 Arithmetic operators on numeric values.
If the target type is xs:float
or xs:double
, the string -0
(and equivalents
such as -0.0
or -000
) should be converted to the value negative zero.
However, if the implementation is reliant on an implementation of XML Schema 1.0 in which negative zero
is not part of the value space for these types, these lexical forms may be converted to positive zero.
In casting to xs:decimal
or to a type derived from xs:decimal
,
if the value is not too large or too small but nevertheless cannot be represented accurately
with the number of decimal digits available to the implementation, the implementation may round
to the nearest representable value or may raise a dynamic error [err:FOCA0006].
The choice of rounding algorithm and the choice between rounding and error behavior and is
·implementation-defined·.
In casting to xs:date
, xs:dateTime
, xs:gYear
,
or xs:gYearMonth
(or types derived from these), if the value is too large or too
small to be represented by the implementation, a dynamic error
[err:FODT0001] is raised.
In casting to a duration value, if the value is too large or too small to be represented by the implementation, a dynamic error [err:FODT0002] is raised.
For xs:anyURI
, the extent to which an implementation validates the
lexical form of xs:anyURI
is ·implementation-dependent·.
If the cast fails for any other reason, a dynamic error [err:FORG0001] is raised.
Casting from xs:string
and xs:untypedAtomic
to any other type
(primitive or non-primitive) has been described in 19.2 Casting from xs:string and xs:untypedAtomic.
This section defines how other casts to non-primitive types operate, including casting
to types derived by restriction, to union types, and to list types.
Note:
A non-primitive type here means any type that is not a ·primitive type· according to the extended definition used in 19 Casting.
Casting a value to a derived type can be separated into four cases. In these rules:
The types xs:untypedAtomic
, xs:integer
, xs:yearMonthDuration
,
and xs:dayTimeDuration
are treated as primitive types (alongside the 19 primitive types defined in XSD).
For any atomic type T, let P(T) denote the most specific primitive type
such that itemType-subtype(T, P(T))
is true.
The rules are then:
When ST is the same type as TT: this case always succeeds, returning SV unchanged.
When itemType-subtype(ST, TT)
is true: This case is described in 19.3.2 Casting from derived types to parent types.
When P(ST) is the same type as P(TT): This case is described in 19.3.3 Casting within a branch of the type hierarchy.
Otherwise (P(ST) is not the same type as P(TT)): This case is described in 19.3.4 Casting across the type hierarchy.
It is always possible to cast an atomic value A to a type T
if the relation A instance of T
is true, provided that T
is not an abstract type.
For example, it is
possible to cast an xs:unsignedShort
to an
xs:unsignedInt
, to an xs:integer
, to an
xs:decimal
, or to a union type
whose member types are xs:integer
and xs:double
.
Since the value space of the original type is a subset of the value space of the target type, such a cast is always successful.
For the expression A instance of T
to be true, T must be
either an atomic type, or a union type that has no constraining facets. It cannot
be a list type, nor a union type derived by restriction from another union type, nor
a union type that has a list type among its member types.
The result will have the same value as the original, but will have a new type annotation:
If T is an atomic type, then the type annotation of the result is T
.
If T is a union type, then the type of the result is an atomic type M
such that M is one of the atomic types in the transitive membership of
the union type T and A instance of M
is true; if there is more
than one type M that satisfies these conditions (which could happen, for example,
if T is the union of two overlapping types such as xs:int
and xs:positiveInteger
) then the first one is used, taking the member types
in the order in which they appear within the definition of the union type.
It is possible to cast an SV to a TT if the type of the
SV and the TT type are both derived by restriction
(directly or indirectly) from the same ·primitive type·, provided that the
supplied value conforms to the constraints implied by the facets of the target
type. This includes the case where the target type is derived from the type of the supplied value,
as well as the case where the type of the supplied value is derived from the target type. For example, an instance of xs:byte
can be cast as
xs:unsignedShort
, provided the value is not negative.
If the value does not conform to the facets defined for the target type, then a dynamic
error is raised [err:FORG0001]. See [XML Schema Part 2: Datatypes Second Edition].
In the case of the pattern facet (which applies to the lexical space rather than
the value space), the pattern is tested against the canonical lexical
representation of the value, as defined for the source type (or the result
of casting the value to an xs:string
, in the case of types that have no canonical
lexical representation defined for them).
Note that this will cause casts to fail if the pattern excludes the canonical
lexical representation of the source type. For example, if the type
my:distance
is defined as a restriction of xs:decimal
with a pattern that requires two digits after the decimal point, casting of an
xs:integer
to my:distance
will always fail, because
the canonical representation of an xs:integer
does not conform to
this pattern.
In some cases, casting from a parent type to a derived type requires special
rules. See 19.1.3 Casting to duration types for rules regarding casting to
xs:yearMonthDuration
and xs:dayTimeDuration
. See 19.1.9 Casting to xs:ENTITY, below, for casting to xs:ENTITY
and types derived from it.
When the ST and the TT are derived, directly or indirectly, from different ·primitive types·, this is called casting across the type hierarchy. Casting across the type hierarchy is logically equivalent to three separate steps performed in order. Errors can occur in either of the latter two steps.
Cast the SV, up the hierarchy, to the ·primitive type· of the source, as described in 19.3.2 Casting from derived types to parent types.
If SV is an instance of xs:string
or xs:untypedAtomic
, check its value against the
pattern facet of TT, and raise a dynamic error [err:FORG0001] if the check fails.
Cast the value to the ·primitive type· of TT, as described in 19.1 Casting from primitive types to primitive types.
If TT is derived from xs:NOTATION
, assume for the
purposes of this rule that casting to xs:NOTATION
succeeds.
Cast the value down to the TT, as described in 19.3.3 Casting within a branch of the type hierarchy
If the target type of a cast expression (or a constructor function) is a type with variety union, the supplied value must be one of the following:
A value of type xs:string
or xs:untypedAtomic
.
This case follows the general rules for casting from strings, and has already been
described in 19.2 Casting from xs:string and xs:untypedAtomic.
If the union type has a pattern facet, the pattern is tested against the supplied
value after whitespace normalization, using the whiteSpace
normalization rules of the member datatype against which validation succeeds.
A value that is an instance of one of the atomic types in the transitive membership of the union type, and of the union type itself. This case has already been described in 19.3.2 Casting from derived types to parent types
This situation only applies when the value is an instance of the union type, which means it will never apply when the union is derived by facet-based restriction from another union type.
A value that is castable to one or more of the atomic types in the transitive membership
of the union type (in the sense that the castable as
operator returns true).
In this case the supplied value is cast to each atomic type in the transitive membership of the union type in turn (in the order in which the member types appear in the declaration) until one of these casts is successful; if none of them is successful, a dynamic error occurs [err:FORG0001]. If the union type has constraining facets then the resulting value must satisfy these facets, otherwise a dynamic error occurs [err:FORG0001].
If the union type has a pattern facet, the pattern is tested against the canonical representation of the result value.
Only the atomic types in the transitive membership of the union type are considered. The
union type may have list types in its transitive membership, but (unless the supplied value
is of type xs:string
or xs:untypedAtomic
, in which case the
rules in 19.2 Casting from xs:string and xs:untypedAtomic apply), any list types in the membership
are effectively ignored.
If more than one of these conditions applies, then the casting is done according to the rules for the first condition that applies.
If none of these conditions applies, the cast fails with a dynamic error [err:FORG0001].
Example: consider a type U whose member types are xs:integer
and xs:date
.
The expression "123" cast as U
returns the
xs:integer
value 123
.
The expression current-date() cast as U
returns
the current date as an instance of xs:date
.
The expression 23.1 cast as U
returns the xs:integer
value 23
.
Example: consider a type V whose member types are xs:short
and xs:negativeInteger
.
The expression "-123" cast as V
returns the
xs:short
value -123
.
The expression "-100000" cast as V
returns the
xs:negativeInteger
value -100000
.
The expression 93.7 cast as V
returns the
xs:short
value 93
.
The expression "93.7" cast as V
raises
a dynamic error [err:FORG0001] on the grounds that the string
"93.7"
is not in the lexical space of the union type.
Example: consider a type W that is derived from the above type V
by restriction, with a pattern facet of -?\d\d
.
The expression "12" cast as V
returns the
xs:short
value 12
.
The expression "123" cast as V
raises
an dynamic error [err:FORG0001] on the grounds that the string
"123"
does not match the pattern facet.
If the target type of a cast expression (or a constructor function) is a
type with variety list
, the supplied value must be of type xs:string
or
xs:untypedAtomic
. The rules follow the general principle for
all casts from xs:string
outlined in 19.2 Casting from xs:string and xs:untypedAtomic.
The semantics of the operation are consistent with validation: that is, the effect of casting a string S to a list type L is the same as constructing an element or attribute node whose string value is S, validating it using L as the governing type, and atomizing the resulting node. The result will always be either failure, or a sequence of zero or more atomic values each of which is an instance of the item type of L (or if the item type of L is a union type, an instance of one of the atomic types in its transitive membership).
If the item type of the list type is namespace-sensitive, then the
namespace bindings in the static context will be used to
resolve any namespace prefix, in the same way as when the target type is
xs:QName
.
If the list type has a pattern
facet, the pattern must match
the supplied value after collapsing whitespace (an operation equivalent to the
use of the fn:normalize-space
function).
For example, the expression cast "A B C D" as xs:NMTOKENS
produces a sequence of four xs:NMTOKEN
values,
("A", "B", "C", "D")
.
For example, given a user-defined type my:coordinates
defined
as a list of xs:integer
with the facet <xs:length value="2"/>
,
the expression my:coordinates("2 -1")
will return a sequence of two
xs:integer values (2, -1)
, while the expression my:coordinates("1 2 3")
will result in a dynamic error because the length of the list does not conform to the
length
facet. The expression my:coordinates("1.0 3.0")
will also fail because the strings 1.0
and 3.0
are not in the lexical space of xs:integer
.