XPath 4.0 implementation
Data model changes
Maps are now ordered: for example, if maps are produced by parsing JSON, the order of entries will be preserved when the map is serialized.
The XDM 4.0 specification changes the rules for maps so that
xs:base64Binary and xs:hexBinary become mutually comparable.
This has the consequence that xs:base64Binary and xs:hexBinary representations
of the same value (for example xs:base64Binary("") and xs:hexBinary(""))
can no longer coexist in the same map in 4.0, whereas they could coexist in 3.1. This
creates a problem because Saxon 13 supports both 3.1 and 4.0 in the same product,
and allows maps to be passed from 3.1 to 4.0 applications and vice versa.
To solve this problem, the version number is held
in the map itself, and determines how values are compared when using that map. Generally,
the version number in the map is 40 if XPath 4.0 was enabled in the application that
constructed the map, or 31 otherwise. However, maps constructed and returned by Saxon
(for example in the result of load-xquery-module) sometimes use 40
unconditionally. The choice is only relevant when entries with binary keys
xs:base64Binary or xs:hexBinary are added to the map.
An ordering is now defined over all instances of xs:duration, not just the
subtypes. A duration is defined to consist of an integer number of months, and a decimal
number of seconds, and the ordering relation takes the number of the months as the primary
key and the number of seconds as the secondary key. This gives sensible results in cases
where the number of seconds in the duration is less than the number of seconds in the
shortest month; but in other cases, such as when comparing the durations
P1M (one month) and P100D (one hundred days), the results are
well defined and well behaved (for example, the relation is transitive and symmetric),
but the answer may make little sense in terms of the real-world calendar.
Function items now have an identity property, enabling them to be compared with
fn:deep-equal().
The handling of year zero in dates (specifically, types xs:dateTime,
xs:date, xs:gYear, and xs:gYearMonth) has changed.
Year zero is now allowed in all cases except when validating a source document against
an XSD schema when XSD 1.0 processing has been requested (the default is XSD 1.1). In this
situation (XSD 1.0 validation), year zero is rejected, but negative years have the XSD 1.1
(and ISO 8601) semantics: that is, year -0001 ends one year before the start of year +0001.
This only affects applications doing arithmetic on dates. This change is consistent with
changes in the draft 4.0 specifications, but it has been made regardless whether 4.0 processing
is enabled in Saxon. The change is also conformant with XPath 3.1, which states
that the results of operations on dates that cross the year 0000 are implementation-defined.
The rules for casting from xs:string when 4.0 is enabled always follow the XSD 1.1 rules.
This means that when casting to xs:date or xs:dateTime,
year zero is accepted regardless of whether the selected XSD version in the Configuration
is 1.0 or 1.1. Similarly, the lexical form +INF (for positive infinity) is always
accepted when casting to xs:double or xs:float. The XSD 1.0 rules continue
to be used for casting if (a) 4.0 is not enabled, and (b) XSD 1.0 processing is selected.
XPath expressions can include namespace declarations, allowing namespace prefixes to be bound within the XPath expression, rather than relying entirely on the host language to declare namespace prefixes.
A URIQualifiedName may now supply a prefix as well as a URI and local name,
in the format Q{uri}prefix:local.
In decimal format properties, it is now possible to set composite values for some properties,
for example percent="%:pc" indicates that the single character "%" will be used
in the picture string, but the value "pc" will appear in the output. (PR 1250)
Changes to XPath Expressions
Four new axes are implemented: following-or-self, preceding-or-self,
following-sibling-or-self, and preceding-sibling-or-self. (PR 1532)
Filter expressions accept a sequence of integer positions, for example $in[3 to 5]
or $in[1, 4, 7].
The pipeline operator -> is implemented, but there has been limited testing
of the case where the context value is not a single item. (PR 1686)
The method call operator =?> is implemented. (PR 2143)
New operators for node comparison expressions are implemented: is-not,
precedes-or-is, follows-or-is; plus precedes and
follows as synonyms for << and >>.
The precedence of the otherwise operator has changed. The expression
@price otherwise @cost * 2 now parses as @price otherwise (@cost * 2),
not as (@price otherwise @cost) * 2. (PR 1031)
The for and let expressions now accept a larger subset
of XQuery FLWOR syntax. Specifically:
-
Both
forandletallow anasclause to declare the variable's type. -
The
forexpression allows anatclause to declare a position variable. -
forandletclauses can be mixed without an interveningreturn, for examplefor $x in $X let $y := $x + 1 return f($y).
Both XQuery and XPath now allow the syntax for key $k $value $v in $map to iterate
over the entries in a map (in undefined order).
Changes to XPath type syntax
Named item types can now be referenced directly by name, rather than using the syntax
type(alias).
Choice item types are implemented, for example the required type of a parameter in a function
signature can be (map(*) | array(*)), indicating that the parameter accepts
either a map or an array. The parentheses are mandatory.
The local union type syntax
union(xs:integer, xs:string) (which only allowed unions of atomic types)
is dropped.
Arrays and maps are coerced to the required type using the 4.0 coercion rules. (PR 1501)
The implementation of enumeration types has been aligned with the current specification. Most practical use cases are unaffected, but:
-
Casting a string to an enumeration type is now allowed.
-
The test
"A" instance of enum("A", "B")now returns true.
XPath 4.0 features not yet implemented
-
PR 2541 - JNodes in a map constructor