[Definition: Under certain circumstances, an atomic value can be promoted from one type to another. Type promotion is used in evaluating function calls (see 4.4.1.1 Static Function Call Syntax) and operators that accept numeric or string operands (see B.2 Operator Mapping).] The following type promotions are permitted:
Numeric type promotion:
A value of type xs:float
(or any type
derived by restriction from xs:float
) can be promoted to
the type xs:double
. The result is the
xs:double
value that is the same as the original
value.
A value of type xs:decimal
(or any type derived
by restriction from xs:decimal
) can be promoted to either
of the types xs:float
or xs:double
. The
result of this promotion is created by casting the original value to
the required type. This kind of promotion may cause loss of
precision.
URI type promotion: A value of type xs:anyURI
(or any type derived by restriction from xs:anyURI
) can be promoted to the type xs:string
. The result of this promotion is created by casting the original value to the type xs:string
.
Note:
Since xs:anyURI
values can be promoted to xs:string
, functions and operators that compare strings using the default collation also compare xs:anyURI
values using the default collation. This ensures that orderings that include strings, xs:anyURI
values, or any combination of the two types are consistent and well-defined.
Note that type promotion is different from subtype substitution. For example:
A function that expects a parameter $p
of type xs:float
can be invoked with a value of type xs:decimal
. This is an example of type promotion. The value is actually converted to the expected type. Within the body of the function, $p instance of xs:decimal
returns false
.
A function that expects a parameter $p
of type xs:decimal
can be invoked with a value of type xs:integer
. This is an example of subtype substitution. The value retains its original type. Within the body of the function, $p instance of xs:integer
returns true
.
The operator mapping tables in this section list the combinations of types for which the various operators of XPath 4.0 are defined. [Definition: For each operator and valid combination of operand types, the operator mapping tables specify a result type and an operator function that implements the semantics of the operator for the given types.] The definitions of the operator functions are given in [XQuery and XPath Functions and Operators 4.0]. The result of an operator may be the raising of an error by its operator function, as defined in [XQuery and XPath Functions and Operators 4.0]. The operator function fully defines the semantics of a given operator for the case where the operands are single atomic values of the types given in the table. For the definition of each operator (including its behavior for empty sequences or sequences of length greater than one), see the descriptive material in the main part of this document.
The and
and
or
operators are defined directly in the main body of
this document, and do not occur in the operator mapping table.
The operators ne
, le
, gt
, and ge
do not
occur in the operator mapping table, but are instead defined by the following equivalences:
A ne B
is equivalent to not(A eq B)
A le B
is equivalent to A lt B or A eq B
A gt B
is equivalent to B lt A
A ge B
is equivalent to B lt A or B eq A
If an operator in the operator mapping tables expects an operand of type
ET, that operator can be applied to an operand of type AT if type AT can
be converted to type ET by a combination of type promotion and subtype substitution. For example, a table entry indicates that the gt
operator may
be applied to two xs:date
operands, returning
xs:boolean
. Therefore, the gt
operator may
also be applied to two (possibly different) subtypes of
xs:date
, also returning xs:boolean
.
[Definition: When referring to a type, the term numeric denotes the types
xs:integer
, xs:decimal
,
xs:float
, and xs:double
which are all member types of the built-in union type xs:numeric
.] An operator whose
operands and result are designated as numeric might be
thought of as representing four operators, one for each of the numeric
types. For example, the numeric +
operator might be
thought of as representing the following four operators:
Operator | First operand type | Second operand type | Result type |
---|---|---|---|
+
|
xs:integer
|
xs:integer
|
xs:integer
|
+
|
xs:decimal
|
xs:decimal
|
xs:decimal
|
+
|
xs:float
|
xs:float
|
xs:float
|
+
|
xs:double
|
xs:double
|
xs:double
|
A numeric operator may be validly applied to an operand of type AT if type
AT can be converted to any of the four numeric types by a combination of
type promotion and subtype substitution. If the result type of an
operator is listed as numeric, it means "the first type in the ordered list (xs:integer, xs:decimal, xs:float, xs:double)
into which all operands can be converted by subtype substitution and type promotion." As an example, suppose that the type hatsize
is derived from xs:integer
and the type shoesize
is derived from xs:float
. Then if the +
operator is invoked with operands of type hatsize
and shoesize
, it returns a result of type xs:float
. Similarly, if +
is invoked with two operands of type hatsize
it returns a result of type xs:integer
.
[Definition: In the operator mapping tables,
the term Gregorian refers to the types
xs:gYearMonth
, xs:gYear
,
xs:gMonthDay
, xs:gDay
, and
xs:gMonth
.] For binary operators that accept two
Gregorian-type operands, both operands must have the same type (for
example, if one operand is of type xs:gDay
, the other
operand must be of type xs:gDay
.)
Operator | Type(A) | Type(B) | Function | Result type |
---|---|---|---|---|
A + B | numeric | numeric | op:numeric-add(A, B) | numeric |
A + B | xs:date | xs:yearMonthDuration | op:add-yearMonthDuration-to-date(A, B) | xs:date |
A + B | xs:yearMonthDuration | xs:date | op:add-yearMonthDuration-to-date(B, A) | xs:date |
A + B | xs:date | xs:dayTimeDuration | op:add-dayTimeDuration-to-date(A, B) | xs:date |
A + B | xs:dayTimeDuration | xs:date | op:add-dayTimeDuration-to-date(B, A) | xs:date |
A + B | xs:time | xs:dayTimeDuration | op:add-dayTimeDuration-to-time(A, B) | xs:time |
A + B | xs:dayTimeDuration | xs:time | op:add-dayTimeDuration-to-time(B, A) | xs:time |
A + B | xs:dateTime | xs:yearMonthDuration | op:add-yearMonthDuration-to-dateTime(A, B) | xs:dateTime |
A + B | xs:yearMonthDuration | xs:dateTime | op:add-yearMonthDuration-to-dateTime(B, A) | xs:dateTime |
A + B | xs:dateTime | xs:dayTimeDuration | op:add-dayTimeDuration-to-dateTime(A, B) | xs:dateTime |
A + B | xs:dayTimeDuration | xs:dateTime | op:add-dayTimeDuration-to-dateTime(B, A) | xs:dateTime |
A + B | xs:yearMonthDuration | xs:yearMonthDuration | op:add-yearMonthDurations(A, B) | xs:yearMonthDuration |
A + B | xs:dayTimeDuration | xs:dayTimeDuration | op:add-dayTimeDurations(A, B) | xs:dayTimeDuration |
A - B | numeric | numeric | op:numeric-subtract(A, B) | numeric |
A - B | xs:date | xs:date | op:subtract-dates(A, B) | xs:dayTimeDuration |
A - B | xs:date | xs:yearMonthDuration | op:subtract-yearMonthDuration-from-date(A, B) | xs:date |
A - B | xs:date | xs:dayTimeDuration | op:subtract-dayTimeDuration-from-date(A, B) | xs:date |
A - B | xs:time | xs:time | op:subtract-times(A, B) | xs:dayTimeDuration |
A - B | xs:time | xs:dayTimeDuration | op:subtract-dayTimeDuration-from-time(A, B) | xs:time |
A - B | xs:dateTime | xs:dateTime | op:subtract-dateTimes(A, B) | xs:dayTimeDuration |
A - B | xs:dateTime | xs:yearMonthDuration | op:subtract-yearMonthDuration-from-dateTime(A, B) | xs:dateTime |
A - B | xs:dateTime | xs:dayTimeDuration | op:subtract-dayTimeDuration-from-dateTime(A, B) | xs:dateTime |
A - B | xs:yearMonthDuration | xs:yearMonthDuration | op:subtract-yearMonthDurations(A, B) | xs:yearMonthDuration |
A - B | xs:dayTimeDuration | xs:dayTimeDuration | op:subtract-dayTimeDurations(A, B) | xs:dayTimeDuration |
A * B | numeric | numeric | op:numeric-multiply(A, B) | numeric |
A * B | xs:yearMonthDuration | numeric | op:multiply-yearMonthDuration(A, B) | xs:yearMonthDuration |
A * B | numeric | xs:yearMonthDuration | op:multiply-yearMonthDuration(B, A) | xs:yearMonthDuration |
A * B | xs:dayTimeDuration | numeric | op:multiply-dayTimeDuration(A, B) | xs:dayTimeDuration |
A * B | numeric | xs:dayTimeDuration | op:multiply-dayTimeDuration(B, A) | xs:dayTimeDuration |
A idiv B | numeric | numeric | op:numeric-integer-divide(A, B) | xs:integer |
A div B | numeric | numeric | op:numeric-divide(A, B) | numeric; but xs:decimal if both operands are xs:integer |
A div B | xs:yearMonthDuration | numeric | op:divide-yearMonthDuration(A, B) | xs:yearMonthDuration |
A div B | xs:dayTimeDuration | numeric | op:divide-dayTimeDuration(A, B) | xs:dayTimeDuration |
A div B | xs:yearMonthDuration | xs:yearMonthDuration | op:divide-yearMonthDuration-by-yearMonthDuration (A, B) | xs:decimal |
A div B | xs:dayTimeDuration | xs:dayTimeDuration | op:divide-dayTimeDuration-by-dayTimeDuration (A, B) | xs:decimal |
A mod B | numeric | numeric | op:numeric-mod(A, B) | numeric |
A eq B | numeric | numeric | op:numeric-equal(A, B) | xs:boolean |
A eq B | xs:boolean | xs:boolean | op:boolean-equal(A, B) | xs:boolean |
A eq B | xs:string | xs:string | op:numeric-equal(fn:compare(A, B), 0) | xs:boolean |
A eq B | xs:date | xs:date | op:date-equal(A, B) | xs:boolean |
A eq B | xs:time | xs:time | op:time-equal(A, B) | xs:boolean |
A eq B | xs:dateTime | xs:dateTime | op:dateTime-equal(A, B) | xs:boolean |
A eq B | xs:duration | xs:duration | op:duration-equal(A, B) | xs:boolean |
A eq B | Gregorian | Gregorian | op:gYear-equal(A, B) etc. | xs:boolean |
A eq B | xs:hexBinary | xs:hexBinary | op:hexBinary-equal(A, B) | xs:boolean |
A eq B | xs:base64Binary | xs:base64Binary | op:base64Binary-equal(A, B) | xs:boolean |
A eq B | xs:QName | xs:QName | op:QName-equal(A, B) | xs:boolean |
A eq B | xs:NOTATION | xs:NOTATION | op:NOTATION-equal(A, B) | xs:boolean |
A eq B | xs:hexBinary | xs:hexBinary | op:hexBinary-equal(A, B) | xs:boolean |
A eq B | xs:base64Binary | xs:base64Binary | op:hexBinary-equal(A, B) | xs:boolean |
A lt B | numeric | numeric | op:numeric-less-than(A, B) | xs:boolean |
A lt B | xs:boolean | xs:boolean | op:boolean-less-than(A, B) | xs:boolean |
A lt B | xs:string | xs:string | op:numeric-less-than(fn:compare(A, B), 0) | xs:boolean |
A lt B | xs:date | xs:date | op:date-less-than(A, B) | xs:boolean |
A lt B | xs:time | xs:time | op:time-less-than(A, B) | xs:boolean |
A lt B | xs:dateTime | xs:dateTime | op:dateTime-less-than(A, B) | xs:boolean |
A lt B | xs:yearMonthDuration | xs:yearMonthDuration | op:yearMonthDuration-less-than(A, B) | xs:boolean |
A lt B | xs:dayTimeDuration | xs:dayTimeDuration | op:dayTimeDuration-less-than(A, B) | xs:boolean |
A lt B | xs:hexBinary | xs:hexBinary | op:hexBinary-less-than(A, B) | xs:boolean |
A lt B | xs:base64Binary | xs:base64Binary | op:base64Binary-less-than(A, B) | xs:boolean |
Operator | Operand type | Function | Result type |
---|---|---|---|
+ A | numeric | op:numeric-unary-plus(A) | numeric |
- A | numeric | op:numeric-unary-minus(A) | numeric |
Various operators written in the grammar using alphabetic keywords (such as and
, or
,
le
, ge
) can instead be written using mathematical symbols. The equivalents are given
in the table below:
Operator | Symbol | Codepoint |
---|---|---|
and | ∧ | x2227 |
or | ∨ | x2228 |
eq | ≐ | x2250 |
ne | ≠ | x2260 |
lt | ⋖ | x22D6 |
gt | ⋗ | x22D7 |
le | ≤ | x2264 |
ge | ≥ | x2265 |
div | ÷ | xF7 |
mod | ||
idiv | ⨸ | x2A38 |
union (|) | ∪ | x222A |
intersect | ∩ | x2229 |
except | ∖ | x2216 |
is | ≡ | x2261 |
<< (precedes) | ≪ | x226A |
>> (follows) | ≫ | x226B |
otherwise | ⊩ | x22A9 |
some | ∃ | x2203 |
every | ∀ | x2200 |
satisfies | ⧴ | x29F4 |
For example, the expression some $x in $X satisfies $x le 17
can equivalently be written
∃ $x in $X ⧴ $x ≤ 17