From fc6154e0ed48e9f462937ab2cd829f5ca415b1d3 Mon Sep 17 00:00:00 2001 From: Michael Kay Date: Mon, 25 Nov 2024 18:21:53 +0000 Subject: [PATCH 01/18] Ordered Maps --- .../src/xpath-datamodel.xml | 68 ++- .../src/function-catalog.xml | 510 ++++++++++++++++-- .../src/xpath-functions.xml | 80 ++- specifications/xquery-40/src/expressions.xml | 28 +- .../xslt-40/src/element-catalog.xml | 7 + specifications/xslt-40/src/xslt.xml | 7 + .../src/xslt-xquery-serialization.xml | 24 +- 7 files changed, 656 insertions(+), 68 deletions(-) diff --git a/specifications/xpath-datamodel-40/src/xpath-datamodel.xml b/specifications/xpath-datamodel-40/src/xpath-datamodel.xml index e5bebcd7b..c8007552e 100644 --- a/specifications/xpath-datamodel-40/src/xpath-datamodel.xml +++ b/specifications/xpath-datamodel-40/src/xpath-datamodel.xml @@ -1511,18 +1511,36 @@ must equal the function’s arity. Constructors are added, and the single accessor function is now an iterator over the key/value pairs in the map. + Ordered maps are introduced.

A map item is a value that represents a map (in other languages this is sometimes called a hash, dictionary, or associative array). - A map is logically a collection of + A map is logically a sequence of key/value pairs. Each key in the map is unique (there is no other key to which it is equal) and has associated with it a value that is a sequence of zero or more items. There is no uniqueness constraint on -values. The semantics of equality are described in +values, only on keys. The semantics of equality when comparing keys are described in .

+

A has +a property called its ordering, which takes one of the three values +random, sorted, or fifo.

+ + +

Random ordering means that the order of entries + in the map is .

+

Sorted ordering means that the keys in the map + are considered to be sorted, and entries are retrieved in order of their keys.

+

Fifo (first-in, first-out) order means that the map + maintains an ordering of entries based on the order in which entries were added, + with new entries being added at the end, after existing entries.

+
+ +

The order of entries in a map + (which is dependent on its ordering + property) is referred to as entry order.

@@ -1538,13 +1556,20 @@ values. The semantics of equality are described in empty-map Constructor - + + +

The dm:empty-map constructor returns a map containing no key/value pairs.

-

The function is exposed in XPath as an empty map constructor, which may be written {} - or map {}.

+

The ordering property of the map is based on the + value of the $ordering argument.

+ +

In XPath an empty map constructor, written as {} + or map {}, creates a map with ordering=random. An empty map with + ordering sorted or fifo can be constructed using functions such as + map:build, map:merge, or map:of-pairs.

@@ -1565,6 +1590,32 @@ values. The semantics of equality are described in

One key/value pair whose key is $key and whose associated value is $value.

+

The ordering property of the returned map is the same + as the ordering of the supplied $map.

+ +

The detailed effect of the function depends on the ordering property, as follows:

+ + +

If the ordering is random, the order of entries in the returned + map is , and bears no necessary relationship + to the ordering of entries in the supplied $map.

+

If the ordering is sorted, the key of the new entry must be + with the keys of existing entries (a dynamic error occurs if this is not + the case), and the ordering of entries in the returned map is such that an entry with key K1 + precedes an entry with key K2 if and only + if fn:compare(K1, K2, $CC) lt 0, + where $CC is the Unicode codepoint collation.

+

Two atomic items + K1 and K2 are strictly comparable if + (a) the function call fn:compare(K1, K2, $CC) (where $CC + is the Unicode codepoint collation) does not fail with a type error, and (b) if one of the values + has a timezone component, then the other also has a timezone component.

+

If the ordering is fifo, then the order of entries in the returned + map reflects the order of entries in the supplied $map. If the key of + the new entry was present in $map then the new entry replaces that entry retaining + its current position; otherwise, the new entry is added after all existing entries.

+
+

The function is exposed in XPath through the function map:put.

@@ -1578,9 +1629,10 @@ values. The semantics of equality are described in -

The dm:iterate-map accessor calls the supplied $action - function once for each key/value pair in $map, in implementation-dependent order, - and returns the sequence concenation of the results.

+

The dm:iterate-map accessor calls the supplied $action + function once for each key/value pair in $map, in order, + and returns the sequence concenation of the results. The order in which entries + are processed reflects the property of the map.

The function is exposed in XPath most directly through the function map:for-each, but it also underpins all other functions giving access to maps, such as map:size, diff --git a/specifications/xpath-functions-40/src/function-catalog.xml b/specifications/xpath-functions-40/src/function-catalog.xml index 84b63f9c1..35ef69084 100644 --- a/specifications/xpath-functions-40/src/function-catalog.xml +++ b/specifications/xpath-functions-40/src/function-catalog.xml @@ -23099,6 +23099,29 @@ xs:QName('xs:double') + + Determines the ordering, and the , of the + entries in the returned map. + + enum("random", "sorted", "fifo") + random + + + The ordering property of the returned map is random, and its + is . + + + The ordering property of the returned map is sorted, and its + is sorted by key. A dynamic error occurs + if the keys are not . + + + The ordering property of the returned map is fifo, and its + reflects the order of the maps supplied in $maps, + and within each input map, the of the entries in that map. + + + @@ -23123,7 +23146,7 @@ let $combine := fn($A as map(*), $B as map(*), $deduplicator as fn(*)) { else map:put($z, $k, $B($k)) }) } -return fold-left($maps, {}, +return fold-left($maps, dm:empty-map($options?ordering otherwise "random"), $combine(?, ?, $duplicates-handler($options?duplicates otherwise "use-first")) ) @@ -23136,6 +23159,9 @@ return fold-left($maps, {}, /> if the value of $options includes an entry whose key is defined in this specification, and whose value is not a permitted value for that key.

+

An error is raised if the option + ordering=sorted is requested, and the keys of the entries to be included in the result are not + .

@@ -23164,7 +23190,8 @@ return fold-left($maps, {},

If the input is an empty sequence, the result is an empty map.

If the input is a sequence of length one, the result map is indistinguishable from the supplied map.

-

There is no requirement that the supplied input maps should have the same or compatible +

Except when ordering=sorted, there is no requirement that + the supplied input maps should have the same or compatible types. The type of a map (for example map(xs:integer, xs:string)) is descriptive of the entries it currently contains, but is not a constraint on how the map may be combined with other maps.

@@ -23235,6 +23262,18 @@ return fold-left($maps, {}, entry that appears in the result is the sequence concatenation of the entries in the input maps, retaining order. + + map:merge(({ "red": 0 }, { "green": 1}, { "blue": 2 }), + { "ordering": "sorted" } => map:keys() + "blue", "green", "red" + The result is in sorted order. + + + map:merge(({ "red": 0 }, { "green": 1}, { "blue": 2 }), + { "ordering": "fifo" } => map:keys() + "red", "green", "blue" + The keys are in first-in, first-out order. + @@ -23247,7 +23286,7 @@ return fold-left($maps, {}, type-ref="key-value-pair" type-ref-occurs="*" usage="inspection" example="{ 'key':'n','value':false() }, { 'key':'y','value':true() }"/> - + @@ -23267,9 +23306,48 @@ return fold-left($maps, {}, $input argument.

-

The optional $combine argument can be used to define how - duplicate keys should be handled. The default is to form the sequence concatenation - of the corresponding values, retaining their order in the input sequence.

+

The $options argument can be used to control the ordering of the result, + and the way in which duplicate keys are handled. + The option parameter conventions apply. +

+ +

The entries that may appear in the $options map are as follows:

+ + + + A function that is used to combine two different values that are supplied + for the same key. The default is to combine the two values using + , retaining their order + in the input sequence. + + (fn(item()*, item()*) as item()*)? + fn:op(',') + + + Determines the ordering, and the , of the + entries in the returned map. + + enum("random", "sorted", "fifo") + random + + + The ordering property of the returned map is random, and its + is . + + + The ordering property of the returned map is sorted, and its + is sorted by key. A dynamic error occurs + if the keys are not . + + + The ordering property of the returned map is fifo, and its + reflects the order of the items supplied in $input. + + + + + + @@ -23277,6 +23355,10 @@ return fold-left($maps, {}, map:build($input, map:get(?, 'key'), map:get(?, 'value'), $combine) +

An error is raised if the option + ordering=sorted is requested, and the keys of the entries to be included in the result are not + .

+

The function can be made to fail with a dynamic error in the event that duplicate keys are present in the input sequence by supplying a $combine function that invokes the fn:error function.

@@ -23366,6 +23448,20 @@ map:build($input, map:get(?, 'key'), map:get(?, 'value'), $combine) In the result map, the value for key 6 is obtained by concatenating the values from the two input maps, with a separator character. + + + map:of-pairs((map:pair("red": 0), map:pair("green": 1), map:pair("blue": 2 )), + { "ordering": "sorted" } => map:keys() + "blue", "green", "red" + The result is in sorted order. + + + + map:of-pairs((map:pair("red": 0), map:pair("green": 1), map:pair("blue": 2 )), + { "ordering": "fifo" } => map:keys() + "red", "green", "blue" + The keys are in first-in, first-out order. + @@ -23391,13 +23487,13 @@ map:build($input, map:get(?, 'key'), map:get(?, 'value'), $combine)

Informally, the function map:keys takes any map as its $map argument and returns - the keys that are present in the map as a sequence of atomic items, in implementation-dependent order.

-

The function is nondeterministic with respect to ordering + the keys that are present in the map as a sequence of atomic items, + in .

+
map:for-each($map, fn($key, $value) { $key }) @@ -23409,11 +23505,21 @@ map:build($input, map:get(?, 'key'), map:get(?, 'value'), $combine) - map:keys({ 1: "yes", 2: "no" }) - (1, 2) + map:keys({ 1: "yes", 0: "no" }) + (1, 0) The result is in implementation-dependent order. + + map:keys({ 1: "yes", 0: "no" } => map:sort()) + (0, 1) + The map is sorted, so the result is in sorted order. + + + map:keys(map:merge(({"red": 0}, {"blue": 1}, {"green": 2}), {"ordering": "fifo"})) + ("red", "blue", "green") + The map has fifo ordering, so the order of keys is predictable. + @@ -23438,15 +23544,15 @@ map:build($input, map:get(?, 'key'), map:get(?, 'value'), $combine) map as its $map argument. The $predicate function takes the key and the value of the corresponding map entry as an argument, and the result is a sequence containing the keys of those - entries for which the predicate function returns true in implementation-dependent order. + entries for which the predicate function returns true in + . A return value of () is treated as false.

-

The function is nondeterministic with respect to ordering + map:for-each($map, fn($key, $value) { @@ -23528,13 +23634,12 @@ return map:keys-where($birthdays, fn($name, $date) {

The function map:items takes any map as its $map argument and returns the values that are present in the map as - a sequence, in implementation-dependent order.

-

The function is nondeterministic with respect to ordering + a sequence, in .

+

The effect of the function is equivalent to $map?*.

@@ -23585,13 +23690,13 @@ return map:keys-where($birthdays, fn($name, $date) { >map
as its $map argument and returns the key-value pairs that are present in the map as a sequence of singleton maps, in implementation-dependent order.

+ def="dt-entry-order"/>.

-

The function is nondeterministic with respect to ordering + @@ -23601,12 +23706,19 @@ return map:keys-where($birthdays, fn($name, $date) { map:entries( - { 1: "yes", 2: "no" } + { 1: "yes", 0: "no" } ) - ({ 1: "yes" }, { 2: "no" }) + ({ 1: "yes" }, { 0: "no" }) The result sequence is in implementation-dependent order. + + map:entries( + { 1: "yes", 0: "no" } => map:sort(), +) + ({ 0: "no" }, { 1: "yes" }) + The result sequence is in key order. + @@ -23634,7 +23746,7 @@ return map:keys-where($birthdays, fn($name, $date) { >map as its $map argument and returns the keys that are present in the map as a sequence of key-value pair maps, in implementation-dependent order.

+ def="dt-entry-order"/>.

A key-value pair map is an instance of type record(key as xs:anyAtomicType, value as item()*): that is a map with two entries, one (with key "key") holding the key, and the other (with key "value") holding the value.

@@ -23900,9 +24012,7 @@ return (

To process an item that is a map, then for each key-value entry (K, V) - in the map (in implementation-dependent order) + in the map (in ) perform both of the following steps, in order:

@@ -23980,6 +24090,9 @@ declare function map:find($input as item()*, + +

Enhanced to allow for ordered maps.

+
@@ -24006,6 +24119,26 @@ declare function map:find($input as item()*, def="dt-same-key" >same key as $key, together with a new entry whose key is $key and whose associated value is $value.

+ +

The ordering property of the returned map is the same as the ordering + property of $map.

+ +

The of the entries in the returned map is as follows:

+ + +

If the ordering is random, then the is + , and has no necessary relationship with the + of $map.

+

If the ordering is sorted, then the is + sorted by key. A dynamic error occurs if the keys are not .

+ +

If the ordering is fifo then:

+ +

If the input $map contains an entry whose

+
+ +
+

The function supplied as $action takes two arguments. It is called supplying the key of the map entry as the first argument, and the associated value as the second argument.

@@ -24320,6 +24488,9 @@ return { depth="5"/>.

+ +

Enhanced to allow for ordered maps.

+
@@ -24348,6 +24519,11 @@ return {

The function supplied as $predicate takes two arguments. It is called supplying the key of the map entry as the first argument, and the associated value as the second argument.

+ +

The ordering property of the returned map is the same as the + ordering property of $map, and in the case of sorted + or fifo ordering the relative order of entries in the returned map + is the same as their relative order in $map.

map:for-each($map, fn($key, $value) { @@ -24375,6 +24551,16 @@ map:for-each($map, fn($key, $value) { ) { 1: "Sunday", 7: "Saturday" } + + map:filter( + { "Sunday": false(), "Monday": true(), "Tuesday": true(), "Wednesday": true(), + "Thursday": true(), "Friday": true(), "Saturday": false() } => map:sort(), + fn($k, $v) { $v } +) + { "Friday": true(), "Monday": true(), "Thursday": true(), + "Tuesday": true(), "Wednesday": true()} + The result is sorted because the input is sorted. + @@ -24384,6 +24570,7 @@ map:for-each($map, fn($key, $value) {

The $predicate callback function may return an empty sequence (meaning false).

+

Enhanced to allow for ordered maps.

@@ -24410,14 +24597,36 @@ map:for-each($map, fn($key, $value) { the supplied $action to the existing value associated with that key.

Otherwise, the returned map contains an entry for the supplied $key whose value is obtained by applying the supplied $action to an empty sequence.

- - +

The ordering property of the returned map is the same as the ordering + property of $map.

+ +

The of the entries in the returned map is as follows:

+ + +

If the ordering is random, then the is + , and has no necessary relationship with the + of $map.

+

If the ordering is sorted, then the is + sorted by key. A dynamic error occurs if the keys are not .

+ +

If the ordering is fifo then:

+ +

If the input $map contains an entry whose

+
+ +
+
if (map:contains($map, $key)) then map:put($map, $key, $action(map:get($map, $key))) else map:put($map, $key, $action(())) + +

An error is raised if the option + ordering=sorted is requested, and the keys of the entries to be included in the result are not + .

+
@@ -24503,7 +24712,7 @@ else map:put($map, $key, $action(())) - + @@ -24522,11 +24731,57 @@ else map:put($map, $key, $action(())) Then, for each key value:

If the key is not already present in the target map, the processor adds a - new key-value pair to the map, with that key and that value.

-

If the key is already present, the processor calls the $combine - function to combine the existing value for the key with the new value, + new key-value pair to the map, with that key and that value.

+

If the key is already present, the processor calls the combine + function in the $options argument to combine the existing value for the key with the new value, and replaces the entry with this combined value.

+ +

The $options argument can be used to control the ordering of the result, + and the way in which duplicate keys are handled. + The option parameter conventions apply. +

+ +

The entries that may appear in the $options map are as follows:

+ + + + A function that is used to combine two different values that are supplied + for the same key. The default is to combine the two values using + . + + (fn(item()*, item()*) as item()*)? + fn:op(',') + + + Determines the ordering, and the , of the + entries in the returned map. + + enum("random", "sorted", "fifo") + random + + + The ordering property of the returned map is random, and its + is . + + + The ordering property of the returned map is sorted, and its + is sorted by key. A dynamic error occurs + if the keys are not . + + + The ordering property of the returned map is fifo, and its + reflects the order of the items supplied in $input, + and within each of those items, the order of the keys returned by the $keys function. + + + + + + + fold-left($input, {}, fn($map, $item, $pos) { @@ -24540,10 +24795,15 @@ fold-left($input, {}, fn($map, $item, $pos) { }) }) + +

An error is raised if the option + ordering=sorted is requested, and the keys of the entries to be included in the result are not + .

+
-

Although defined to process the input sequence in order, this is only relevant when combining the entries - for duplicate keys.

+

The default function for both $keys and $value is the identity function. Although it is permitted to default both, this serves little purpose: usually at least one of these arguments will be supplied.

@@ -24603,7 +24863,7 @@ fold-left($input, {}, fn($map, $item, $pos) { ("apple", "apricot", "banana", "blueberry", "cherry"), substring(?, 1, 1), string-length#1, - op("+") + { "combine": op("+") } ) { "a": 12, "b": 15, "c": 6 } Constructs a map where the key is the first character of an input item, and where the corresponding value @@ -24659,7 +24919,7 @@ return map:build($titles/title, fn($title) { $title/ix })

The following expression creates a map whose keys are employee @location values, and whose corresponding values represent the number of employees at each distinct location. Any employees that lack an @location attribute will be excluded from the result.

- map:build(//employee, fn { @location }, fn { 1 }, op("+")) + map:build(//employee, fn { @location }, fn { 1 }, { "combine": op("+") })

The following expression creates a map whose keys are employee @location values, and whose @@ -24717,6 +24977,136 @@ return map:build($titles/title, fn($title) { $title/ix }) + + + + + + + + + deterministic + context-independent + focus-independent + + +

Returns a sorted map with the same entries as a supplied map.

+ + +

The function map:sort takes any map + as its $map argument and returns a sorted map containing the + same entries.

+
+ + map:of-pairs(map:pairs($map), {'ordering': 'sorted'}) + + +

An error is raised if + the keys in $map are not + .

+
+ +

If the ordering property of $map is sorted, + then $map is returned unchanged.

+
+ + + + map:sort({ "a": 0, "z": 0, "q": 0 }) => map:keys() + "a", "q", "z" + + + map:sort({}) => map:put("x", 0) => map:put("a", 0) => map:keys() + "a", "x" + Adding entries to a sorted map, even if it is empty, produces a sorted map + + + + +

New in 4.0

+
+ + + + + + + + + + + + + + + deterministic + context-independent + focus-independent + + +

Returns a sorted map containing a subset of the entries of a supplied map.

+
+ +

The function filters the supplied $map to return those entries that are + within a given range of values.

+

The entries selected are those, up to a maximum count of $limit if specified, where the + key K satisfies all the following conditions:

+ + +

If $min-inclusive is supplied, then K is + greater than or equal to $min-inclusive

+

If $min-exclusive is supplied, then K is + greater than $min-exclusive

+

If $max-inclusive is supplied, then K is + less than or equal to $max-inclusive

+

If $max-exclusive is supplied, then K is + less than $max-exclusive

+
+
+ +let $CC := "http://www.w3.org/2005/xpath-functions/collation/codepoint" +return map:pairs(map:sort($map)) [ + (empty($min-inclusive) or compare(?key, $min-inclusive, $CC) ge 0) and + (empty($min-exclusive) or compare(?key, $min-exclusive, $CC) gt 0) and + (empty($max-inclusive) or compare(?key, $max-exclusive, $CC) le 0) and + (empty($max-inclusive) or compare(?key, $max-exclusive, $CC) le 0) +] => subsequence(1, $limit otherwise xs:double('+INF')) + => map:of-pairs({ "ordering": "sorted" }) + + +

An error is raised if + the keys in $map are not + .

+
+ +

The function is intended primarily to take advantage of efficiencies that + become possible when the supplied $map has ordering=sorted, + but it still works if the input is not sorted.

+

It would be unusual to supply both $min-inclusive and $min-exclusive, + or both $max-inclusive and $max-exclusive, but all combinations are permitted.

+
+ + + + map:sort({ "a": 1, "b": 2, "c": 3 }) => map:range(max-inclusive:="b") + { "a": 1, "b": 2 } + + + map:sort({ "a": 1, "b": 2, "c": 3 }) => map:range(min-inclusive:="b", max-exclusive="d") + { "b": 2, "c": 3 } + + + map:sort({ "aa": 1, "bb": 2, "cc": 3 }) => map:range(min-inclusive:="b", limit:=1) => map:keys() + "bb" + Returns the first key greater than or equal to the supplied value. + + + + +

New in 4.0

+
+
@@ -25184,6 +25574,19 @@ return $M(collation-key("a", $C)) + + + Determines whether the XML representation of a JSON object should retain the order + of entries in the input. + xs:boolean + true + + The children of any fn:map element in the output will be + in order. + The children of any fn:map element in the output will be + in the same order as the corresponding entries in the JSON input. + + Determines whether the generated XML tree is schema-validated. @@ -25694,7 +26097,8 @@ return json-to-xml($json, $options)]]> the children of the map element, enclosed between curly braces and separated by commas. Each entry comprises the value of the key attribute of the child element, enclosed in quotation marks and escaped as described below, followed by a colon, followed by the result of processing the child element - by applying these rules recursively.

+ by applying these rules recursively. The order of properties in the output JSON representation retains the order + of the children of the map element.

Comments, processing instructions, and whitespace text node children of map and array @@ -27116,6 +27520,19 @@ return document { + + + Determines whether maps resulting from parsing of JSON objects should retain the input order. + xs:boolean + false + + Any maps resulting from parsing of JSON objects have the ordering + property set to random. + Any maps resulting from parsing of JSON objects have the ordering + property set to fifo, and the retains the order + of entries in the input. + + Determines whether special characters are represented in the XDM output in backslash-escaped form. @@ -27245,6 +27662,7 @@ return document { { "x": 2, "y": 5 }.

If duplicate keys are encountered in a JSON object, they are handled as determined by the duplicates option defined above.

+

The order of entries is retained if the retain-order option is set to true.

A JSON array is transformed to an array whose members are the result of converting diff --git a/specifications/xpath-functions-40/src/xpath-functions.xml b/specifications/xpath-functions-40/src/xpath-functions.xml index 3bd25371a..bf1774911 100644 --- a/specifications/xpath-functions-40/src/xpath-functions.xml +++ b/specifications/xpath-functions-40/src/xpath-functions.xml @@ -7626,12 +7626,13 @@ return Maps +

Maps were introduced as a new datatype in XDM 3.1. This section describes functions that operate on maps.

-

A map is an additional kind of item.

+

A map is a kind of item.

-

A map consists of a set of entries, also known +

A map consists of a sequence of entries, also known as key-value pairs. Each entry comprises a key which is an arbitrary atomic item, and an arbitrary sequence called the associated value.

@@ -7659,6 +7660,73 @@ return
The fact that a map is a function item allows it to be passed as an argument to higher-order functions that expect a function item as one of their arguments.

+ + Ordering of Maps + + + Ordered maps are introduced. + + +

A map has a property called its ordering, + which takes one of the values random, sorted, or fifo.

+ + +

Random is the default ordering, and was the only value available in + earlier versions of this specification. With random ordering, the order of entries in the + map is : with many implementations, it is likely + to be entirely unpredictable, based on some internal hashing function applied to the keys.

+ +

Sorted ordering maintains and delivers the entries in a map in ascending + order of the keys. This imposes a constraint that the keys must be .

+

A set of keys + is strictly comparable if for every pair of keys K1 + and K2, (a) the function fn:compare(K1, K2, $CC), + where $CC is the Unicode Codepoint Collation, can be evaluated without raising a type error, + and (b) if either K1 or K2 has a timezone component, then both have + a timezone component.

+

This disallows types such as xs:QName for which no ordering is defined, + and also disallows mixing of types such as xs:string and xs:integer + in the same map. The ordering chosen in context-independent, which means that strings + are always compared using the Unicode codepoint collation, and date/time values must either + all have a timezone, or all have no timezone.

+
+ +

Fifo (first-in, first-out) ordering maintains and delivers the + entries in a map in the order they were added: new entries are added at the end. The detailed + rules are determined by the map:put function.

+
+ +

A sorted map may be constructed using the map:sort function. Adding or removing + entries to a sorted map will maintain the sort order. In some cases it is convenient to + construct an empty map with the property ordering=sorted using the + expression map:sort({}), and then build the map by adding entries incrementally. + Alternatively, a sorted map may be constructed by calling any of the functions + map:build, map:merge, or map:of-pairs with + the option ordering=sorted.

+ +

A map with ordering fifo may be constructed by calling any of the functions + map:build, map:merge, or map:of-pairs with + the option ordering=fifo. These functions may be used to construct an empty + map with this ordering property, to which entries can then be added incrementally; or they + may be used to construct a map in which the order of entries reflect the order of items + in the sequence supplied as input.

+ +

Maps with ordering fifo are also constructed by certain operations such + as parse-json and xml-to-json.

+ +

The order of entries in a map + (which is dependent on its ordering + property) is referred to as entry order.

+

The of the entries in a map is + respected by functions such as map:entries, + map:keys, map:values, map:pairs, map:for-each, and + json-to-xml. It also affects the result of the expression + for key $k value $v return EXPR, and the output + of the json and adaptive serialization methods.

+ + +
+ Composing and Decomposing Maps @@ -7740,7 +7808,7 @@ return
Formal Specification of Maps

The XDM data model () defines three primitive operations on maps:

-

dm:empty-map constructs an empty map.

+

dm:empty-map constructs an empty map with a given ordering property.

dm:map-put adds or replaces an entry in a map.

dm:iterate-map applies a supplied function to every entry in a map.

@@ -13162,6 +13230,12 @@ ISBN 0 521 77752 6. or key contains an invalid JSON escape sequence.

+ +

Raised by various functions if an attempt is made to construct a map with the ordering + property set to sorted when the keys to be included in the map + are not .

+
+ diff --git a/specifications/xquery-40/src/expressions.xml b/specifications/xquery-40/src/expressions.xml index fd74b7925..68181c02a 100644 --- a/specifications/xquery-40/src/expressions.xml +++ b/specifications/xquery-40/src/expressions.xml @@ -16923,7 +16923,7 @@ let $z := g($x, $y)]]>

When a ForEntryBinding is used (that is, when either or both of the keywords key and value are used), the key range variable (if present) is bound in turn to each key in the map - (in order), and the value + (in entry order), and the value range variable (if present) is bound to the corresponding value.

In this case the corresponding ExprSingle must evaluate to a single map, otherwise a type error is raised

+ +

The ordering property of a map constructed using a map constructor expression + is random.

+ + +

A map with sorted ordering can be created by applying the map:sort + function.

+

A map with fifo ordering can be created by use of the functions map:build, + map:merge, or map:of-pairs with the option { "ordering": "fifo" }.

+
Constructing a fixed map @@ -19931,6 +19941,9 @@ processing with JSON processing.

the result is the same as $V?pairs::(map:keys($V)).

The order of entries in the result sequence in this case + reflects the entry order + of the map. In the default case where the ordering of the + map is random, the order of entries in the result sequence is implementation-dependent.

@@ -20555,7 +20568,12 @@ return $array?[count(.) ge 2] The context position is the position of the entry in the map (in an arbitrary ordering), and the context size is the number of entries in the map. The result of the expression is a map containing those entries of the input map for which - the of the FILTER expression is true.

+ the of the FILTER expression is true. + The ordering property of the result is the same as the ordering + property of the input map, and in the case of sorted or fifo + ordering the relative order of entries in the result retains the relative order of entries + in the input. +

For example, the following expression:

@@ -20567,8 +20585,10 @@ return $map?[?key ge 2] { 2: "beta", 3: "gamma" } -

Filtering of maps based on numeric positions is not generally useful, because the order of entries - in a map is unpredictable; but it is available in the interests of orthogonality.

+

Filtering of maps based on numeric positions is not generally useful when + the ordering of the map is random, + because the order of entries in a map is unpredictable; but it is available + in the interests of orthogonality.

diff --git a/specifications/xslt-40/src/element-catalog.xml b/specifications/xslt-40/src/element-catalog.xml index fdaa0f0ed..b28deeeb5 100644 --- a/specifications/xslt-40/src/element-catalog.xml +++ b/specifications/xslt-40/src/element-catalog.xml @@ -1665,6 +1665,13 @@ + + + + + + + diff --git a/specifications/xslt-40/src/xslt.xml b/specifications/xslt-40/src/xslt.xml index e939395b8..082c7b92f 100644 --- a/specifications/xslt-40/src/xslt.xml +++ b/specifications/xslt-40/src/xslt.xml @@ -35624,6 +35624,13 @@ the same group, and the--> the union of the map entries from the supplied sequence of maps.

+

If the ordering attribute is present then its is used + as the value of the ordering option in the call to map:merge.

+ + +

The effect of the three different map ordering options is explained in .

+
+

The handling of duplicate keys is described in below.

diff --git a/specifications/xslt-xquery-serialization-40/src/xslt-xquery-serialization.xml b/specifications/xslt-xquery-serialization-40/src/xslt-xquery-serialization.xml index 80429956c..bc12d5fff 100644 --- a/specifications/xslt-xquery-serialization-40/src/xslt-xquery-serialization.xml +++ b/specifications/xslt-xquery-serialization-40/src/xslt-xquery-serialization.xml @@ -3451,13 +3451,16 @@ the string value of the key the serialized JSON value of the entry, separated by delimiters according to the JSON object syntax, i.e. {key:value, key:value, ...}. -The order in which each key/value pair appears -in the serialized output is -implementation-dependent.

-When map items are serialized using the JSON +The key/value pairs in the serialized output retain the + entry order of entries in the map.

+ +

The order is implementation-dependent in + the default case where the ordering + property of the map is random.

+

If any two keys of the map item have the same string value, serialization error is raised, @@ -3851,9 +3854,16 @@ to output parentheses around a singleton if this avoids buffering data in memory A map item is serialized using the syntax of a without the optional map keyword, that is in the format {key:value, key:value, ...}. -The order of entries is implementation-dependent. The key is serialized by applying the rules +The key/value pairs in the serialized output retain the + entry order of entries in the map. + The key is serialized by applying the rules for serializing an atomic item. The values are serialized in the same way as the members of an array (see above). -

+

+ +

The order of entries is implementation-dependent in + the default case where the ordering + property of the map is random.

+

A function item is serialized to the representation name#A where From 903115f279dbdd30eca7b5184ec8e275b43c97a3 Mon Sep 17 00:00:00 2001 From: Michael Kay Date: Mon, 25 Nov 2024 19:11:19 +0000 Subject: [PATCH 02/18] Include map:sort and map:range --- specifications/xpath-functions-40/src/xpath-functions.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/specifications/xpath-functions-40/src/xpath-functions.xml b/specifications/xpath-functions-40/src/xpath-functions.xml index bf1774911..2584e0122 100644 --- a/specifications/xpath-functions-40/src/xpath-functions.xml +++ b/specifications/xpath-functions-40/src/xpath-functions.xml @@ -7902,6 +7902,9 @@ return

+ + + @@ -7911,6 +7914,9 @@ return
+ + + From 55be1bcd22e8f6247742eb587deae2e38eb42a8c Mon Sep 17 00:00:00 2001 From: Michael Kay Date: Wed, 27 Nov 2024 00:32:21 +0000 Subject: [PATCH 03/18] Simplify spec of map:range --- .../src/function-catalog.xml | 81 ++++++++++++------- 1 file changed, 51 insertions(+), 30 deletions(-) diff --git a/specifications/xpath-functions-40/src/function-catalog.xml b/specifications/xpath-functions-40/src/function-catalog.xml index 35ef69084..4fb1b3d04 100644 --- a/specifications/xpath-functions-40/src/function-catalog.xml +++ b/specifications/xpath-functions-40/src/function-catalog.xml @@ -25032,11 +25032,9 @@ return map:build($titles/title, fn($title) { $title/ix }) - - - - - + + + @@ -25050,29 +25048,39 @@ return map:build($titles/title, fn($title) { $title/ix })

The function filters the supplied $map to return those entries that are within a given range of values.

-

The entries selected are those, up to a maximum count of $limit if specified, where the +

The function first selects those entries whose key K satisfies all the following conditions:

-

If $min-inclusive is supplied, then K is - greater than or equal to $min-inclusive

-

If $min-exclusive is supplied, then K is - greater than $min-exclusive

-

If $max-inclusive is supplied, then K is - less than or equal to $max-inclusive

-

If $max-exclusive is supplied, then K is - less than $max-exclusive

+

If $min is supplied, then K is + greater than or equal to $min.

+

If $max is supplied, then K is + less than $max.

+ +

If $count is specified, then:

+ +

If $count is positive and is less than the number of selected + entries, it then selects the first $count of these entries, in key order.

+

If $count is negative and -$count is less than the number of selected + entries, it then selects the last -$count of these entries, in key order.

+
+ +

For example, specifying count := 1 selects the first qualifying entry, while + count := -1 selects the last.

let $CC := "http://www.w3.org/2005/xpath-functions/collation/codepoint" -return map:pairs(map:sort($map)) [ - (empty($min-inclusive) or compare(?key, $min-inclusive, $CC) ge 0) and - (empty($min-exclusive) or compare(?key, $min-exclusive, $CC) gt 0) and - (empty($max-inclusive) or compare(?key, $max-exclusive, $CC) le 0) and - (empty($max-inclusive) or compare(?key, $max-exclusive, $CC) le 0) -] => subsequence(1, $limit otherwise xs:double('+INF')) - => map:of-pairs({ "ordering": "sorted" }) +let $pairs := map:pairs(map:sort($map)) [ + (empty($min) or compare(?key, $min, $CC) ge 0) and + (empty($max) or compare(?key, $max, $CC) lt 0) +] +let $slice := + if ($count gt 0) then slice($pairs, 1, $count) + else if ($count lt 0) then slice($pairs, -$count, -1) + else $pairs +return + map:of-pairs($slice, { "ordering": "sorted" })

An error is raised if @@ -25083,22 +25091,35 @@ return map:pairs(map:sort($map)) [

The function is intended primarily to take advantage of efficiencies that become possible when the supplied $map has ordering=sorted, but it still works if the input is not sorted.

-

It would be unusual to supply both $min-inclusive and $min-exclusive, - or both $max-inclusive and $max-exclusive, but all combinations are permitted.

+

Note that $min is an inclusive bound, while $max is exclusive. + If $min is omitted, the selection starts at the first entry in $map, + and if $max is omitted, the selection ends at the last entry.

- + - map:sort({ "a": 1, "b": 2, "c": 3 }) => map:range(max-inclusive:="b") - { "a": 1, "b": 2 } + map:sort({ "a": 1, "c": 3, "b": 2 }) => map:range(count:=1) + { "a": 1 } + Selects the first entry in the map, in key order + + + map:sort({ "a": 1, "c": 3, "b": 2 }) => map:range(count:=-1) + { "c": 3 } + Selects the last entry in the map, in key order + + + map:sort({ "a": 1, "c": 3, "b": 2 }) => map:range(max:="b") + { "a": 1, "b": 2 } - map:sort({ "a": 1, "b": 2, "c": 3 }) => map:range(min-inclusive:="b", max-exclusive="d") - { "b": 2, "c": 3 } + map:sort({ "a": 1, "c": 3, "b": 2 }) => map:range(min:="b", max="d") + { "b": 2, "c": 3 } - map:sort({ "aa": 1, "bb": 2, "cc": 3 }) => map:range(min-inclusive:="b", limit:=1) => map:keys() - "bb" + map:sort({ "aa": 1, "cc": 3, "bb": 2 }) + => map:range(min:="b", count:=1) + => map:keys() + "bb" Returns the first key greater than or equal to the supplied value. From d292eee36588ce6bb2b8c3d31fcd813d1238e0af Mon Sep 17 00:00:00 2001 From: Michael Kay Date: Wed, 27 Nov 2024 10:25:07 +0000 Subject: [PATCH 04/18] Rename "fifo" ordering as "insertion" ordering --- .../src/xpath-datamodel.xml | 8 ++-- .../src/function-catalog.xml | 42 +++++++++---------- .../src/xpath-functions.xml | 8 ++-- .../xslt-40/src/element-catalog.xml | 2 +- 4 files changed, 30 insertions(+), 30 deletions(-) diff --git a/specifications/xpath-datamodel-40/src/xpath-datamodel.xml b/specifications/xpath-datamodel-40/src/xpath-datamodel.xml index c8007552e..176239dad 100644 --- a/specifications/xpath-datamodel-40/src/xpath-datamodel.xml +++ b/specifications/xpath-datamodel-40/src/xpath-datamodel.xml @@ -1526,7 +1526,7 @@ values, only on keys. The semantics of equality when comparing keys are describe

A has a property called its ordering, which takes one of the three values -random, sorted, or fifo.

+random, sorted, or insertion.

Random ordering means that the order of entries @@ -1557,7 +1557,7 @@ a property called its ordering, which takes one of the three values empty-map Constructor - + @@ -1568,7 +1568,7 @@ a property called its ordering, which takes one of the three values

In XPath an empty map constructor, written as {} or map {}, creates a map with ordering=random. An empty map with - ordering sorted or fifo can be constructed using functions such as + ordering sorted or insertion can be constructed using functions such as map:build, map:merge, or map:of-pairs.

@@ -1610,7 +1610,7 @@ a property called its ordering, which takes one of the three values (a) the function call fn:compare(K1, K2, $CC) (where $CC is the Unicode codepoint collation) does not fail with a type error, and (b) if one of the values has a timezone component, then the other also has a timezone component.

-

If the ordering is fifo, then the order of entries in the returned +

If the ordering is insertion, then the order of entries in the returned map reflects the order of entries in the supplied $map. If the key of the new entry was present in $map then the new entry replaces that entry retaining its current position; otherwise, the new entry is added after all existing entries.

diff --git a/specifications/xpath-functions-40/src/function-catalog.xml b/specifications/xpath-functions-40/src/function-catalog.xml index 4fb1b3d04..41108bc60 100644 --- a/specifications/xpath-functions-40/src/function-catalog.xml +++ b/specifications/xpath-functions-40/src/function-catalog.xml @@ -23103,7 +23103,7 @@ xs:QName('xs:double') Determines the ordering, and the , of the entries in the returned map. - enum("random", "sorted", "fifo") + enum("random", "sorted", "insertion") random @@ -23115,8 +23115,8 @@ xs:QName('xs:double') is sorted by key. A dynamic error occurs if the keys are not . - - The ordering property of the returned map is fifo, and its + + The ordering property of the returned map is insertion, and its reflects the order of the maps supplied in $maps, and within each input map, the of the entries in that map. @@ -23270,7 +23270,7 @@ return fold-left($maps, dm:empty-map($options?ordering otherwise "random"), map:merge(({ "red": 0 }, { "green": 1}, { "blue": 2 }), - { "ordering": "fifo" } => map:keys() + { "ordering": "insertion" } => map:keys() "red", "green", "blue" The keys are in first-in, first-out order. @@ -23327,7 +23327,7 @@ return fold-left($maps, dm:empty-map($options?ordering otherwise "random"), Determines the ordering, and the , of the entries in the returned map. - enum("random", "sorted", "fifo") + enum("random", "sorted", "insertion") random @@ -23339,8 +23339,8 @@ return fold-left($maps, dm:empty-map($options?ordering otherwise "random"), is sorted by key. A dynamic error occurs if the keys are not . - - The ordering property of the returned map is fifo, and its + + The ordering property of the returned map is insertion, and its reflects the order of the items supplied in $input. @@ -23458,7 +23458,7 @@ map:build($input, map:get(?, 'key'), map:get(?, 'value'), $combine) map:of-pairs((map:pair("red": 0), map:pair("green": 1), map:pair("blue": 2 )), - { "ordering": "fifo" } => map:keys() + { "ordering": "insertion" } => map:keys() "red", "green", "blue" The keys are in first-in, first-out order. @@ -23516,9 +23516,9 @@ map:build($input, map:get(?, 'key'), map:get(?, 'value'), $combine) The map is sorted, so the result is in sorted order. - map:keys(map:merge(({"red": 0}, {"blue": 1}, {"green": 2}), {"ordering": "fifo"})) + map:keys(map:merge(({"red": 0}, {"blue": 1}, {"green": 2}), {"ordering": "insertion"})) ("red", "blue", "green") - The map has fifo ordering, so the order of keys is predictable. + The map has insertion ordering, so the order of keys is predictable.
@@ -24132,7 +24132,7 @@ declare function map:find($input as item()*,

If the ordering is sorted, then the is sorted by key. A dynamic error occurs if the keys are not .

-

If the ordering is fifo then:

+

If the ordering is insertion then:

If the input $map contains an entry whose

@@ -24180,7 +24180,7 @@ declare function map:find($input as item()*, there is no requirement that the type of $key and $value be consistent with the types of any existing keys and values in the supplied map.

-

With ordering=fifo, you can force the new entry to go at the end of the sequence by calling +

With ordering=insertion, you can force the new entry to go at the end of the sequence by calling map:remove before calling map:put.

@@ -24203,14 +24203,14 @@ declare function map:find($input as item()*, map:put(parse-json('{ "red": 0, "green": 1, "blue" 2 }), "yellow", -1) => map:keys() "red", "green", "blue", "yellow" - The result of fn:parse-json has ordering=fifo, + The result of fn:parse-json has ordering=insertion, so the new entry is added at the end of the list. map:put(parse-json('{ "red": 0, "green": 1, "blue" 2 }), "red", -1) => map:keys() "red", "green", "blue" - The result of fn:parse-json has ordering=fifo, + The result of fn:parse-json has ordering=insertion, changing the value for an existing key does not change the order of the keys. @@ -24365,7 +24365,7 @@ map:of-pairs((

No failure occurs if an item in $keys does not correspond to any entry in $map; that key value is simply ignored.

The ordering property of the returned map is the same as the ordering property - of $map, and in the case of ordering sorted or fifo, the relative + of $map, and in the case of ordering sorted or insertion, the relative position of retained entries in the result map is the same as their relative position in $map.

@@ -24522,7 +24522,7 @@ return {

The ordering property of the returned map is the same as the ordering property of $map, and in the case of sorted - or fifo ordering the relative order of entries in the returned map + or insertion ordering the relative order of entries in the returned map is the same as their relative order in $map.

@@ -24609,7 +24609,7 @@ map:for-each($map, fn($key, $value) {

If the ordering is sorted, then the is sorted by key. A dynamic error occurs if the keys are not .

-

If the ordering is fifo then:

+

If the ordering is insertion then:

If the input $map contains an entry whose

@@ -24759,7 +24759,7 @@ else map:put($map, $key, $action(())) Determines the ordering, and the , of the entries in the returned map. - enum("random", "sorted", "fifo") + enum("random", "sorted", "insertion") random @@ -24771,8 +24771,8 @@ else map:put($map, $key, $action(())) is sorted by key. A dynamic error occurs if the keys are not . - - The ordering property of the returned map is fifo, and its + + The ordering property of the returned map is insertion, and its reflects the order of the items supplied in $input, and within each of those items, the order of the keys returned by the $keys function. @@ -27550,7 +27550,7 @@ return document { Any maps resulting from parsing of JSON objects have the ordering property set to random. Any maps resulting from parsing of JSON objects have the ordering - property set to fifo, and the retains the order + property set to insertion, and the retains the order of entries in the input. diff --git a/specifications/xpath-functions-40/src/xpath-functions.xml b/specifications/xpath-functions-40/src/xpath-functions.xml index 2584e0122..cefcd73de 100644 --- a/specifications/xpath-functions-40/src/xpath-functions.xml +++ b/specifications/xpath-functions-40/src/xpath-functions.xml @@ -7668,7 +7668,7 @@ return

A map has a property called its ordering, - which takes one of the values random, sorted, or fifo.

+ which takes one of the values random, sorted, or insertion.

Random is the default ordering, and was the only value available in @@ -7704,14 +7704,14 @@ return

map:build, map:merge, or map:of-pairs with the option ordering=sorted.

-

A map with ordering fifo may be constructed by calling any of the functions +

A map with ordering insertion may be constructed by calling any of the functions map:build, map:merge, or map:of-pairs with - the option ordering=fifo. These functions may be used to construct an empty + the option ordering=insertion. These functions may be used to construct an empty map with this ordering property, to which entries can then be added incrementally; or they may be used to construct a map in which the order of entries reflect the order of items in the sequence supplied as input.

-

Maps with ordering fifo are also constructed by certain operations such +

Maps with ordering insertion are also constructed by certain operations such as parse-json and xml-to-json.

The order of entries in a map diff --git a/specifications/xslt-40/src/element-catalog.xml b/specifications/xslt-40/src/element-catalog.xml index b28deeeb5..0f97d5ce2 100644 --- a/specifications/xslt-40/src/element-catalog.xml +++ b/specifications/xslt-40/src/element-catalog.xml @@ -1669,7 +1669,7 @@ - + From 15bfa682a72e3e5afe9fc347f73160ba5bd5f0da Mon Sep 17 00:00:00 2001 From: Michael Kay Date: Wed, 27 Nov 2024 11:14:20 +0000 Subject: [PATCH 05/18] Revise ordering rules for parse-json, xml-to-json, json-to-xml. --- .../src/function-catalog.xml | 51 ++++++++----------- .../src/xpath-functions.xml | 2 +- 2 files changed, 22 insertions(+), 31 deletions(-) diff --git a/specifications/xpath-functions-40/src/function-catalog.xml b/specifications/xpath-functions-40/src/function-catalog.xml index 41108bc60..c2a561237 100644 --- a/specifications/xpath-functions-40/src/function-catalog.xml +++ b/specifications/xpath-functions-40/src/function-catalog.xml @@ -24091,7 +24091,7 @@ declare function map:find($input as item()*, -

Enhanced to allow for ordered maps.

+

Enhanced to allow for ordered maps.

@@ -24200,23 +24200,25 @@ declare function map:find($input as item()*, 4: "Donnerstag", 5: "Freitag", 6: "Samstag", -1: "Unbekannt" } - map:put(parse-json('{ "red": 0, "green": 1, "blue" 2 }), - "yellow", -1) => map:keys() + parse-json('{ "red": 0, "green": 1, "blue" 2 }', {'retain-order': true()}) + => map:put("yellow", -1) + => map:keys() "red", "green", "blue", "yellow" - The result of fn:parse-json has ordering=insertion, + The result of fn:parse-json is in insertion order, so the new entry is added at the end of the list. - map:put(parse-json('{ "red": 0, "green": 1, "blue" 2 }), - "red", -1) => map:keys() + parse-json('{ "red": 0, "green": 1, "blue" 2 }', {'retain-order': true()}) + => map:put("red", -1) + => map:keys() "red", "green", "blue" - The result of fn:parse-json has ordering=insertion, - changing the value for an existing key does not change the order of the keys. + The result of fn:parse-json is in insertion order, + so changing the value for an existing key does not change the order of the keys. -

Enhanced to allow for ordered maps.

+

Enhanced to allow for ordered maps.

@@ -24400,7 +24402,7 @@ map:filter($map, fn($k, $v) { not(some($keys, atomic-equal($k, ?))) }) -

Enhanced to allow for ordered maps.

+

Enhanced to allow for ordered maps.

@@ -24489,7 +24491,7 @@ return { -

Enhanced to allow for ordered maps.

+

Enhanced to allow for ordered maps.

@@ -24570,7 +24572,7 @@ map:for-each($map, fn($key, $value) {

The $predicate callback function may return an empty sequence (meaning false).

-

Enhanced to allow for ordered maps.

+

Enhanced to allow for ordered maps.

@@ -25024,7 +25026,7 @@ return map:build($titles/title, fn($title) { $title/ix }) -

New in 4.0

+

New in 4.0

@@ -25125,7 +25127,7 @@ return -

New in 4.0

+

New in 4.0

@@ -25595,19 +25597,6 @@ return $M(collation-key("a", $C)) - - - Determines whether the XML representation of a JSON object should retain the order - of entries in the input. - xs:boolean - true - - The children of any fn:map element in the output will be - in order. - The children of any fn:map element in the output will be - in the same order as the corresponding entries in the JSON input. - - Determines whether the generated XML tree is schema-validated. @@ -25767,8 +25756,8 @@ return $M(collation-key("a", $C))

The XDM tree returned by the function does not contain any unnecessary (albeit valid) nodes such as whitespace text nodes, comments, or processing instructions. It does not include any whitespace in the value of number or boolean - element nodes, or in the value of escaped or escaped-key - attribute nodes.

+ element nodes, nor in the value of escaped or escaped-key + attribute nodes.

If the result is typed, every element named string will have an attribute named @@ -27841,7 +27830,9 @@ return document { specification gave the default value as true, but this appears to have been an error, since it was inconsistent with examples given in the specification and with tests in the test suite.

- + +

An option is provided to retain the order of entries in maps.

+
diff --git a/specifications/xpath-functions-40/src/xpath-functions.xml b/specifications/xpath-functions-40/src/xpath-functions.xml index cefcd73de..52e2770f2 100644 --- a/specifications/xpath-functions-40/src/xpath-functions.xml +++ b/specifications/xpath-functions-40/src/xpath-functions.xml @@ -6922,7 +6922,7 @@ correctly in all browsers, depending on the system configuration.

--> of numbers, the conversion is not guaranteed to retain full precision.

Although the order of entries in a JSON object is generally considered to have no significance, the functions - json-to-xml and json-to-xml both retain order.

+ json-to-xml and xml-to-json both retain order.

The XDM representation of a JSON value may either be untyped (all elements annotated as xs:untyped, attributes as xs:untypedAtomic), or it may be typed. If it is typed, then it must have the type From 8a5882c246125fbe4bad80b788c92ef32dfb0563 Mon Sep 17 00:00:00 2001 From: Michael Kay Date: Wed, 27 Nov 2024 11:18:42 +0000 Subject: [PATCH 06/18] One more reference to "FIFO" becomes "insertion" --- specifications/xpath-functions-40/src/xpath-functions.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specifications/xpath-functions-40/src/xpath-functions.xml b/specifications/xpath-functions-40/src/xpath-functions.xml index 52e2770f2..ad75416f5 100644 --- a/specifications/xpath-functions-40/src/xpath-functions.xml +++ b/specifications/xpath-functions-40/src/xpath-functions.xml @@ -7691,7 +7691,7 @@ return

all have a timezone, or all have no timezone.

-

Fifo (first-in, first-out) ordering maintains and delivers the +

Insertion ordering maintains and delivers the entries in a map in the order they were added: new entries are added at the end. The detailed rules are determined by the map:put function.

From f2f5aac503f4f327dae07bb6a78205b12bafcecd Mon Sep 17 00:00:00 2001 From: Michael Kay Date: Wed, 27 Nov 2024 11:43:58 +0000 Subject: [PATCH 07/18] Deem that map ordering does not affect deep-equals. --- specifications/xpath-functions-40/src/function-catalog.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/specifications/xpath-functions-40/src/function-catalog.xml b/specifications/xpath-functions-40/src/function-catalog.xml index c2a561237..0676c5f82 100644 --- a/specifications/xpath-functions-40/src/function-catalog.xml +++ b/specifications/xpath-functions-40/src/function-catalog.xml @@ -16539,6 +16539,8 @@ declare function equal-strings( +

It is not required that both maps have the same ordering property, + nor that the order of entries matches.

All the following conditions are true:

From b2d54b93d1b1725d363b846b40246e0374f6f812 Mon Sep 17 00:00:00 2001 From: Michael Kay Date: Tue, 3 Dec 2024 14:32:02 +0000 Subject: [PATCH 08/18] Copy edits --- specifications/xpath-datamodel-40/src/xpath-datamodel.xml | 6 +++--- specifications/xquery-40/src/expressions.xml | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/specifications/xpath-datamodel-40/src/xpath-datamodel.xml b/specifications/xpath-datamodel-40/src/xpath-datamodel.xml index 176239dad..438f980b3 100644 --- a/specifications/xpath-datamodel-40/src/xpath-datamodel.xml +++ b/specifications/xpath-datamodel-40/src/xpath-datamodel.xml @@ -1533,7 +1533,7 @@ a property called its ordering, which takes one of the three values in the map is .

Sorted ordering means that the keys in the map are considered to be sorted, and entries are retrieved in order of their keys.

-

Fifo (first-in, first-out) order means that the map +

Insertion ordering (first-in, first-out) means that the map maintains an ordering of entries based on the order in which entries were added, with new entries being added at the end, after existing entries.

@@ -1608,8 +1608,8 @@ a property called its ordering, which takes one of the three values

Two atomic items K1 and K2 are strictly comparable if (a) the function call fn:compare(K1, K2, $CC) (where $CC - is the Unicode codepoint collation) does not fail with a type error, and (b) if one of the values - has a timezone component, then the other also has a timezone component.

+ is the Unicode codepoint collation) does not fail with a type error, and (b) either both of the values + have a timezone component, or neither of them has a timezone component.

If the ordering is insertion, then the order of entries in the returned map reflects the order of entries in the supplied $map. If the key of the new entry was present in $map then the new entry replaces that entry retaining diff --git a/specifications/xquery-40/src/expressions.xml b/specifications/xquery-40/src/expressions.xml index 68181c02a..bed1ab174 100644 --- a/specifications/xquery-40/src/expressions.xml +++ b/specifications/xquery-40/src/expressions.xml @@ -19352,8 +19352,8 @@ processing with JSON processing.

A map with sorted ordering can be created by applying the map:sort function.

-

A map with fifo ordering can be created by use of the functions map:build, - map:merge, or map:of-pairs with the option { "ordering": "fifo" }.

+

A map with insertion ordering can be created by use of the functions map:build, + map:merge, or map:of-pairs with the option { "ordering": "insertion" }.

@@ -20570,7 +20570,7 @@ return $array?[count(.) ge 2] of the expression is a map containing those entries of the input map for which the of the FILTER expression is true. The ordering property of the result is the same as the ordering - property of the input map, and in the case of sorted or fifo + property of the input map, and in the case of sorted or insertion ordering the relative order of entries in the result retains the relative order of entries in the input.

From a925abff5df707537fd23e06318c421b1730d834 Mon Sep 17 00:00:00 2001 From: Michael Kay Date: Tue, 3 Dec 2024 17:45:13 +0000 Subject: [PATCH 09/18] map ordering: "random" changes to "undefined" --- .../src/xpath-datamodel.xml | 8 ++--- .../src/function-catalog.xml | 36 +++++++++---------- .../src/xpath-functions.xml | 6 ++-- specifications/xquery-40/src/expressions.xml | 6 ++-- .../xslt-40/src/element-catalog.xml | 4 +-- .../src/xslt-xquery-serialization.xml | 4 +-- 6 files changed, 32 insertions(+), 32 deletions(-) diff --git a/specifications/xpath-datamodel-40/src/xpath-datamodel.xml b/specifications/xpath-datamodel-40/src/xpath-datamodel.xml index 438f980b3..d3a3760dd 100644 --- a/specifications/xpath-datamodel-40/src/xpath-datamodel.xml +++ b/specifications/xpath-datamodel-40/src/xpath-datamodel.xml @@ -1526,7 +1526,7 @@ values, only on keys. The semantics of equality when comparing keys are describe

A has a property called its ordering, which takes one of the three values -random, sorted, or insertion.

+undefined, sorted, or insertion.

Random ordering means that the order of entries @@ -1557,7 +1557,7 @@ a property called its ordering, which takes one of the three values empty-map Constructor - + @@ -1567,7 +1567,7 @@ a property called its ordering, which takes one of the three values value of the $ordering argument.

In XPath an empty map constructor, written as {} - or map {}, creates a map with ordering=random. An empty map with + or map {}, creates a map with ordering=undefined. An empty map with ordering sorted or insertion can be constructed using functions such as map:build, map:merge, or map:of-pairs.

@@ -1596,7 +1596,7 @@ a property called its ordering, which takes one of the three values

The detailed effect of the function depends on the ordering property, as follows:

-

If the ordering is random, the order of entries in the returned +

If the ordering is undefined, the order of entries in the returned map is , and bears no necessary relationship to the ordering of entries in the supplied $map.

If the ordering is sorted, the key of the new entry must be diff --git a/specifications/xpath-functions-40/src/function-catalog.xml b/specifications/xpath-functions-40/src/function-catalog.xml index 0676c5f82..9f79048ca 100644 --- a/specifications/xpath-functions-40/src/function-catalog.xml +++ b/specifications/xpath-functions-40/src/function-catalog.xml @@ -23105,11 +23105,11 @@ xs:QName('xs:double') Determines the ordering, and the , of the entries in the returned map. - enum("random", "sorted", "insertion") - random + enum("undefined", "sorted", "insertion") + undefined - - The ordering property of the returned map is random, and its + + The ordering property of the returned map is undefined, and its is . @@ -23148,7 +23148,7 @@ let $combine := fn($A as map(*), $B as map(*), $deduplicator as fn(*)) { else map:put($z, $k, $B($k)) }) } -return fold-left($maps, dm:empty-map($options?ordering otherwise "random"), +return fold-left($maps, dm:empty-map($options?ordering otherwise "undefined"), $combine(?, ?, $duplicates-handler($options?duplicates otherwise "use-first")) ) @@ -23329,11 +23329,11 @@ return fold-left($maps, dm:empty-map($options?ordering otherwise "random"), Determines the ordering, and the , of the entries in the returned map. - enum("random", "sorted", "insertion") - random + enum("undefined", "sorted", "insertion") + undefined - - The ordering property of the returned map is random, and its + + The ordering property of the returned map is undefined, and its is . @@ -24128,7 +24128,7 @@ declare function map:find($input as item()*,

The of the entries in the returned map is as follows:

-

If the ordering is random, then the is +

If the ordering is undefined, then the is , and has no necessary relationship with the of $map.

If the ordering is sorted, then the is @@ -24246,7 +24246,7 @@ declare function map:find($input as item()*, entry. The key of the entry in the new map is $key, and its associated value is $value.

-

The ordering property of the returned map is random.

+

The ordering property of the returned map is undefined.

@@ -24305,7 +24305,7 @@ map:merge(//book ! map:entry(isbn, .))]]> >map
which contains two entries, one (with the key "key") containing $key and the other (with the key "value") containing $value.

-

The ordering property of the returned map is random.

+

The ordering property of the returned map is undefined.

{} @@ -24607,7 +24607,7 @@ map:for-each($map, fn($key, $value) {

The of the entries in the returned map is as follows:

-

If the ordering is random, then the is +

If the ordering is undefined, then the is , and has no necessary relationship with the of $map.

If the ordering is sorted, then the is @@ -24763,11 +24763,11 @@ else map:put($map, $key, $action(())) Determines the ordering, and the , of the entries in the returned map. - enum("random", "sorted", "insertion") - random + enum("undefined", "sorted", "insertion") + undefined - - The ordering property of the returned map is random, and its + + The ordering property of the returned map is undefined, and its is . @@ -27539,7 +27539,7 @@ return document { false Any maps resulting from parsing of JSON objects have the ordering - property set to random. + property set to undefined. Any maps resulting from parsing of JSON objects have the ordering property set to insertion, and the retains the order of entries in the input. diff --git a/specifications/xpath-functions-40/src/xpath-functions.xml b/specifications/xpath-functions-40/src/xpath-functions.xml index ad75416f5..21d621b8d 100644 --- a/specifications/xpath-functions-40/src/xpath-functions.xml +++ b/specifications/xpath-functions-40/src/xpath-functions.xml @@ -7668,11 +7668,11 @@ return

A map has a property called its ordering, - which takes one of the values random, sorted, or insertion.

+ which takes one of the values undefined, sorted, or insertion.

-

Random is the default ordering, and was the only value available in - earlier versions of this specification. With random ordering, the order of entries in the +

Undefined is the default ordering, and was the only value available in + earlier versions of this specification. With undefined ordering, the order of entries in the map is : with many implementations, it is likely to be entirely unpredictable, based on some internal hashing function applied to the keys.

diff --git a/specifications/xquery-40/src/expressions.xml b/specifications/xquery-40/src/expressions.xml index bed1ab174..a22c9df6c 100644 --- a/specifications/xquery-40/src/expressions.xml +++ b/specifications/xquery-40/src/expressions.xml @@ -19347,7 +19347,7 @@ processing with JSON processing.

The ordering property of a map constructed using a map constructor expression - is random.

+ is undefined.

A map with sorted ordering can be created by applying the map:sort @@ -19943,7 +19943,7 @@ processing with JSON processing.

The order of entries in the result sequence in this case reflects the entry order of the map. In the default case where the ordering of the - map is random, the order of entries in the result sequence + map is undefined, the order of entries in the result sequence is implementation-dependent.

@@ -20586,7 +20586,7 @@ return $map?[?key ge 2]

Filtering of maps based on numeric positions is not generally useful when - the ordering of the map is random, + the ordering of the map is undefined, because the order of entries in a map is unpredictable; but it is available in the interests of orthogonality.

diff --git a/specifications/xslt-40/src/element-catalog.xml b/specifications/xslt-40/src/element-catalog.xml index 0f97d5ce2..efecf268e 100644 --- a/specifications/xslt-40/src/element-catalog.xml +++ b/specifications/xslt-40/src/element-catalog.xml @@ -1665,9 +1665,9 @@ - + - + diff --git a/specifications/xslt-xquery-serialization-40/src/xslt-xquery-serialization.xml b/specifications/xslt-xquery-serialization-40/src/xslt-xquery-serialization.xml index bc12d5fff..dfcc862fe 100644 --- a/specifications/xslt-xquery-serialization-40/src/xslt-xquery-serialization.xml +++ b/specifications/xslt-xquery-serialization-40/src/xslt-xquery-serialization.xml @@ -3456,7 +3456,7 @@ The key/value pairs in the serialized output retain the

The order is implementation-dependent in the default case where the ordering - property of the map is random.

+ property of the map is undefined.

+ map:for-each($map, fn($key, $value) { $key }) @@ -23543,7 +23546,7 @@ map:build($input, map:get(?, 'key'), map:get(?, 'value'), $combine) - nondeterministic-wrt-ordering + deterministic context-independent focus-independent @@ -23555,9 +23558,11 @@ map:build($input, map:get(?, 'key'), map:get(?, 'value'), $combine) map as its $map argument. The $predicate function takes the key and the value of the corresponding map entry as an argument, and the result is a sequence containing the keys of those - entries for which the predicate function returns true in - entry order. - A return value of () is treated as false.

+ entries for which the predicate function returns true, in + entry order.

+ +

A return value of () from the predicate function is + treated as false.

+

The effect of the function is equivalent to $map?*.

@@ -23688,7 +23689,7 @@ return map:keys-where($birthdays, fn($name, $date) { - nondeterministic-wrt-ordering + deterministic context-independent focus-independent @@ -23703,11 +23704,7 @@ return map:keys-where($birthdays, fn($name, $date) { a sequence of singleton maps, in entry order.

- + @@ -23744,7 +23741,7 @@ return map:keys-where($birthdays, fn($name, $date) { - nondeterministic-wrt-ordering + deterministic context-independent focus-independent @@ -23761,11 +23758,7 @@ return map:keys-where($birthdays, fn($name, $date) {

A key-value pair map is an instance of type record(key as xs:anyAtomicType, value as item()*): that is a map with two entries, one (with key "key") holding the key, and the other (with key "value") holding the value.

-

The function is nondeterministic with respect to ordering - (see ). This means that two calls with the same argument - are not guaranteed to produce the results in the same order.

+ map:for-each($map, map:pair#2) @@ -23810,8 +23803,11 @@ return map:keys-where($birthdays, fn($name, $date) {

Returns the ordering property of a map.

-

The function returns the value of the ordering property of a map: - one of undefined, sorted, or insertion.

+

The function returns the value of the + property of a map: + one of , + , or + .

@@ -24177,22 +24173,23 @@ declare function map:find($input as item()*, >same key as $key, together with a new entry whose key is $key and whose associated value is $value.

-

The ordering property of the returned map is the same as the ordering +

The property of the returned map + is the same as the property of $map.

The entry order of the entries in the returned map is as follows:

-

If the ordering is undefined, then the +

If the ordering is , then the entry order is , and has no necessary relationship with the entry order of $map.

-

If the ordering is sorted, then the +

If the ordering is , then the entry order is sorted by key. A dynamic error occurs if the keys are not .

-

If the ordering is insertion then:

+

If the ordering is then:

If the input $map contains an entry whose

@@ -24230,9 +24227,13 @@ declare function map:find($input as item()*,
-

An error is raised if the ordering - property has the value sorted is requested, and the keys of the entries to be included in the result are not - .

+

An error is raised if the + + property of $map has the value + , + and the $key is not + + with every key present in $map.

@@ -24304,7 +24305,8 @@ declare function map:find($input as item()*, entry. The key of the entry in the new map is $key, and its associated value is $value.

-

The ordering property of the returned map is undefined.

+

The property + of the returned map is .

@@ -24363,7 +24365,8 @@ map:merge(//book ! map:entry(isbn, .))]]> >map which contains two entries, one (with the key "key") containing $key and the other (with the key "value") containing $value.

-

The ordering property of the returned map is undefined.

+

The property of the returned + map is .

{} @@ -24474,7 +24477,7 @@ map:filter($map, fn($k, $v) { not(some($keys, atomic-equal($k, ?))) }) - nondeterministic-wrt-ordering + deterministic context-independent focus-independent @@ -24488,11 +24491,7 @@ map:filter($map, fn($k, $v) { not(some($keys, atomic-equal($k, ?))) }) >map as its $map argument and applies the supplied function to each entry in the map, in entry order; the result is the of the results of these function calls.

- +

The function supplied as $action takes two arguments. It is called supplying the key of the map entry as the first argument, and the associated value as the second argument.

@@ -24581,9 +24580,11 @@ return { supplying the key of the map entry as the first argument, and the associated value as the second argument.

-

The ordering property of the returned map is the same as the - ordering property of $map, and in the case of sorted - or insertion ordering the relative order of entries in the returned map +

The property of the returned map is the same as the + property of $map, and in the case of + + or + ordering the relative order of entries in the returned map is the same as their relative order in $map.

@@ -24820,7 +24821,7 @@ else map:put($map, $key, $action(())) fn:op(',') - Determines the ordering, and the + Determines the , and the entry order, of the entries in the returned map. @@ -24828,17 +24829,20 @@ else map:put($map, $key, $action(())) undefined - The ordering property of the returned map is undefined, and its + The ordering property of the returned map is + , and its entry order is . - The ordering property of the returned map is sorted, and its + The ordering property of the returned map is + , and its entry order is sorted by key. A dynamic error occurs if the keys are not . - The ordering property of the returned map is insertion, and its + The ordering property of the returned map is + , and its entry order reflects the order of the items supplied in $input, and within each of those items, the order of the keys returned by the $keys function. @@ -34076,6 +34080,8 @@ return $result is derived from V by applying the function derived-value(M', K, V), defined below.

+

The and + of M are retained in M'.

If $input is an array A, the result is an array A' diff --git a/specifications/xpath-functions-40/src/xpath-functions.xml b/specifications/xpath-functions-40/src/xpath-functions.xml index b0f42966e..a9b574259 100644 --- a/specifications/xpath-functions-40/src/xpath-functions.xml +++ b/specifications/xpath-functions-40/src/xpath-functions.xml @@ -808,6 +808,7 @@ Michael Sperberg-McQueen (1954–2024).

All entries in the options map are optional, and supplying an empty map has the same effect as omitting the relevant argument in the function call, assuming this is permitted.

+

The ordering of the options map is immaterial.

For each named option, the function specification defines a required type for the option value. The value that is actually supplied in the map is converted to this required type using the @@ -863,16 +864,19 @@ the relationship of various item types.

in declaring the types of variables or the argument types and result types of functions.

-

Item types in the data model form a directed graph, rather than a +

In XDM, item types include node types, +function types, and built-in atomic types. +Item types form a directed graph, rather than a hierarchy or lattice: in the relationship defined by the derived-from(A, B) function, some types are derived from more than one other type. Examples include functions (function(xs:string) as xs:int is substitutable for function(xs:NCName) as xs:int and also for -function(xs:string) as xs:decimal), and union types -(A is substitutable for the union type (A | B) and also -for (A | C). In XDM, item types include node types, -function types, and built-in atomic types. The diagram, which shows +function(xs:string) as xs:decimal), and choice types +(A is substitutable for the choice type (A | B) and also +for (A | C). Record types provide an alternative way of categorizing + maps: the instances of record(longitude, latitude) overlap with + the instances of map(xs:string, xs:double). The diagram, which shows only hierarchic relationships, is therefore a simplification of the full model.

@@ -7900,7 +7904,7 @@ return
to be specified by reference to this function library, without risk of circularity.

There is one exception to this rule: for convenience, the notation {} is used to represent - an empty map, in preference to a call on dm:empty-map().

+ an empty map, in preference to a call on dm:empty-map(ordering := 'undefined').

The formal equivalents are not intended to provide a realistic way of implementating the functions (in particular, any real implementation might be expected to implement map:get diff --git a/specifications/xquery-40/src/expressions.xml b/specifications/xquery-40/src/expressions.xml index 5dfea8f10..67f1c5076 100644 --- a/specifications/xquery-40/src/expressions.xml +++ b/specifications/xquery-40/src/expressions.xml @@ -19241,6 +19241,28 @@ processing with JSON processing.

see . For an overview of the functions available for processing maps, see .

+ + +

Maps in &language; have a property called , + which takes three possible values: undefined, sorted, + and insertion. The effect of these three options is explained + in . In summary:

+ +

The value undefined means that the order of entries + in the map is ; it may, for example, + be the result of a randomized hashing algorithm.

+

The value sorted means that the map maintains entries + sorted in key order. If this option is chosen then it is required that the + keys be mutually comparable: an error will result if there is a key whose + data type does not define ordering (for example, xs:QName), or if + there are two keys whose data types are not mutually comparable (for example, + xs:integer and xs:string). Strings are sorted + using the Unicode Codepoint Collation.

+

The value insertion means that the map will retain entries + in the order of the initial sequence that results from evaluation of the + contained sequence constructor.

+
+
Map Constructors @@ -19460,9 +19482,11 @@ processing with JSON processing.

map:of-pairs(//employee ! {'key':@id, 'value':.})

-

All three functions also provide control over how duplicate keys are handled, - allowing them to be used to create a map in which items are grouped according - to the value of a grouping key.

+

All three functions also provide control over:

+ +

The way in which duplicate keys are handled, and

+

The ordering of entries in the resulting map.

+
@@ -20079,7 +20103,8 @@ processing with JSON processing.

}

then ?*[. instance of record(street, postcode)]?postcode - returns ("MK12 2EX", "EX8 9AA") (or some permutation thereof).

+ returns ("MK12 2EX", "EX8 9AA") (or some permutation thereof, + depending on the of the map).

Writing ?*?postcode would raise a type error, because the result of the initial step ?* includes an item (the string "John Smith") that is neither a map nor an array.

diff --git a/specifications/xquery-40/src/query-prolog.xml b/specifications/xquery-40/src/query-prolog.xml index e0cfefd68..5801d19ff 100644 --- a/specifications/xquery-40/src/query-prolog.xml +++ b/specifications/xquery-40/src/query-prolog.xml @@ -2143,7 +2143,7 @@ local:depth(doc("partlist.xml")) , so the order of entries corresponds to the order of field declarations in the record type. This means, for example, that when the map is serialized using the JSON output method, the order of entries in the output will - be predictable.

+ correspond to the order of field declarations.

If a field is declared as optional, by including a question mark after the name, and if it has no initializer, then the initializer := () is added implicitly. If the declared type of an optional field does diff --git a/specifications/xslt-40/src/xslt.xml b/specifications/xslt-40/src/xslt.xml index 082c7b92f..4e5b0d646 100644 --- a/specifications/xslt-40/src/xslt.xml +++ b/specifications/xslt-40/src/xslt.xml @@ -35596,7 +35596,10 @@ the same group, and the--> attribute and a sequence constructor are present. - + + Ordered maps are introduced. + +

Two instructions are added to XSLT to facilitate the construction of maps.

@@ -35617,18 +35620,38 @@ the same group, and the-->

In the absense of duplicate keys, the result of the instruction is then given by the XPath 3.1 expression:

- map:merge($maps) + map:merge($maps, { 'ordering': $ordering }) + +

where $ordering is the of the ordering + attribute, defaulting to "undefined".

Informally: in the absence of duplicate keys the resulting map contains the union of the map entries from the supplied sequence of maps.

-

If the ordering attribute is present then its is used - as the value of the ordering option in the call to map:merge.

-

The effect of the three different map ordering options is explained in .

+

The effect of the three different map ordering options is explained + in . In summary:

+ +

The value undefined means that the order of entries + in the map is ; it may, for example, + be the result of a randomized hashing algorithm.

+

The value sorted means that the map maintains entries + sorted in key order. If this option is chosen then it is required that the + keys be mutually comparable: an error will result if there is a key whose + data type does not define ordering (for example, xs:QName), or if + there are two keys whose data types are not mutually comparable (for example, + xs:integer and xs:string). Strings are sorted + using the Unicode Codepoint Collation.

+

The value insertion means that the map will retain entries + in the order of the initial sequence that results from evaluation of the + contained sequence constructor.

+
+

The selected ordering applies not only to the map that is returned from this + xsl:map instruction, but also to any maps that are subsequently derived + from this by adding or removing entries.

The handling of duplicate keys is described in below.

@@ -35636,8 +35659,9 @@ the same group, and the--> -

There is no requirement that the maps in the input sequence should have the same or - compatible types. The type of a map (for example map(xs:integer, +

There is no requirement that the supplied input maps should have the same or + compatible types, except for sorted maps where the keys must be comparable. + The type of a map (for example map(xs:integer, xs:string)) is descriptive of the entries it currently contains, but is not a constraint on how the map may be combined with other maps.

diff --git a/specifications/xslt-xquery-serialization-40/src/xslt-xquery-serialization.xml b/specifications/xslt-xquery-serialization-40/src/xslt-xquery-serialization.xml index dfcc862fe..db94b8707 100644 --- a/specifications/xslt-xquery-serialization-40/src/xslt-xquery-serialization.xml +++ b/specifications/xslt-xquery-serialization-40/src/xslt-xquery-serialization.xml @@ -3455,7 +3455,7 @@ The key/value pairs in the serialized output retain the entry order of entries in the map.

The order is implementation-dependent in - the default case where the ordering + the default case where the ordering property of the map is undefined.

- + @@ -34080,7 +34005,8 @@ return $result is derived from V by applying the function derived-value(M', K, V), defined below.

-

The and +

The property + and of M are retained in M'.

diff --git a/specifications/xpath-functions-40/src/xpath-functions.xml b/specifications/xpath-functions-40/src/xpath-functions.xml index a9b574259..e7d8bbc5e 100644 --- a/specifications/xpath-functions-40/src/xpath-functions.xml +++ b/specifications/xpath-functions-40/src/xpath-functions.xml @@ -7671,102 +7671,33 @@ return
Ordered maps are introduced. -

A map has a property called its ordering, - which takes one of the values - undefined, - sorted, or - insertion.

+

A map has a property called ordered, + which takes the value true or false.

-

Undefined is the default ordering, and was the only value available in - earlier versions of this specification. With undefined ordering, the order of entries in the - map is : with many implementations, it is likely +

By default, the ordered propery is false, + in which case the map is said to be unordered. The order of entries in an unordered map + is : with many implementations, it is likely to be entirely unpredictable, based on some internal hashing function applied to the keys.

-

Sorted ordering maintains and delivers the entries in a map in ascending - order of the keys. This imposes a constraint that the keys must be .

-

A set of keys - is strictly comparable if for every pair of keys K1 - and K2, (a) the function fn:compare(K1, K2, $CC), - where $CC is the Unicode Codepoint Collation, can be evaluated without raising a type error, - and (b) if either K1 or K2 has a timezone component, then both have - a timezone component.

-

This disallows types such as xs:QName for which no ordering is defined, - and also disallows mixing of types such as xs:string and xs:integer - in the same map. The ordering chosen in context-independent, which means that strings - are always compared using the Unicode codepoint collation, and date/time values must either - all have a timezone, or all have no timezone.

-
- -

Insertion ordering maintains and delivers the - entries in a map in the order they were added: new entries are added at the end. The detailed +

In a map whose ordered propery is true, + entries in a map are delivered in the order they were added: + new entries are added at the end. The detailed rules are determined by the map:put function.

The entry order of a map - (which is dependent on its ordering - property) is referred to as entry order.

+ is referred to as entry order.

The entry order of the entries in a map is respected by functions such as map:entries, - map:keys, map:values, map:pairs, map:for-each, and + map:keys, map:values, map:pairs, + map:for-each, and json-to-xml. It also affects the result of the expression for key $k value $v return EXPR, and the output of the json and adaptive serialization methods.

-

Maps with ordering sorted or insertion are - described in more detail in the following sections.

- - - Using Sorted Maps - -

A sorted map can be constructed either by applying the map:sort function - to an existing map, or by constructing an empty map with the sorted property, and then adding - entries to it incrementally. The simplest way to construct an empty map with - the sorted property is with the function call map:sort({}). Sorted - maps can also be constructed using the map:build, map:of-pairs, - or map:merge functions with the option { "ordering" : "sorted" }.

- -

There are a number of possible reasons for using sorted maps (which in most implementations - are likely to incur some overhead, in space and time, relative to maps whose ordering - is undefined).

- - -

One reason is to achieve sorted output. For example, serializing a sorted map - using the JSON output method will output the entries in key order. Although the order - of entries in a JSON object typically has no semantic meaning, there are many operations - that retain order when JSON is parsed and this may be useful, for example, when generating - reports.

-

Similarly, the expression for key $key value $value return EXPR - will process a sorted map in key order, which may be useful when generating an output - report.

-

The json-to-xml function also preserves the order of entries - in JSON objects in the generated XML.

-

There is of course no guarantee that putting data into a sorted map and then iterating - over the map will be faster than using fn:sort (or other constructs) to - sort the data. But if the sorted data is required repeatedly, then it makes sense to - maintain the data in sorted order rather than performing repeated sorts.

-
-

A second reason is to enable range searching. The function map:range - can be used to select all the entries from a sorted map where the key is in a given - range of values. For example, if a map holds information about events with the date and time - of the event as a key value, a range search enables all the events in a given week to - found efficiently; it also enables finding the first event after or before - a given date and time.

-

(The map:range function will also work on an input map that is not - sorted, but it is likely to be much less efficient in this case.)

- -
- - -

Adding or removing entries to a sorted map will maintain the sort order, as will - calls to functions such as map:filter and map:find.

- -
- - Using Maps with Insertion Ordering -

Maps with ordering insertion - have two main uses:

+

Ordered maps have two main uses:

When a map is constructed in a single operation, for example @@ -7784,12 +7715,12 @@ return

In the first case the map will typically be constructed using a function such as map:build, map:of-pairs, or map:merge - with the option { 'ordering': 'insertion' }. + with the option { 'retain-order': true() }. The entry order of the map will then reflect the order of items in the original input sequence.

-

In the second case, an empty map with insertion ordering will typically be created - using a function call such as map:build({}, { 'ordering': 'insertion' }), +

In the second case, an empty ordered map will typically be created + using a function call such as map:build({}, { 'retain-order': true() }), and entries will then be added incrementally by successive calls on map:put, often within a processing loop controlled using fn:fold-left, or in XSLT xsl:iterate.

@@ -7798,16 +7729,14 @@ return
returns a map in which the order of entries in the constructor is lost; this mechanism cannot therefore be used to construct a map with predictable order of entries. Instead, the required effect can be achieved with the expression - map:merge(({ "first": 1 }, { "second": 2 }), { 'ordering': 'insertion' }).

+ map:merge(({ "first": 1 }, { "second": 2 }), { 'ordered': true() }).

-

Maps with ordering insertion - can also be constructed by certain operations such +

Ordered maps can also be constructed by certain operations such as parse-json and xml-to-json.

- @@ -7977,8 +7906,8 @@ return
- - + + @@ -7989,9 +7918,6 @@ return
- - - @@ -8001,9 +7927,7 @@ return
- - - + @@ -13323,12 +13247,7 @@ ISBN 0 521 77752 6. or key contains an invalid JSON escape sequence.

- -

Raised by various functions if an attempt is made to construct a map with the ordering - property set to sorted when the keys to be included in the map - are not .

-
- + diff --git a/specifications/xquery-40/src/expressions.xml b/specifications/xquery-40/src/expressions.xml index 67f1c5076..5c260a9a7 100644 --- a/specifications/xquery-40/src/expressions.xml +++ b/specifications/xquery-40/src/expressions.xml @@ -5408,7 +5408,7 @@ name.

is an instance of K and every value is an instance of V.

-

The ordering +

The ordered and entry-order properties of a map have no effect on whether the map matches a particular map type.

@@ -5617,7 +5617,7 @@ name.

Although constructors for named record types produce a map in which the entry order reflects the order of field definitions in the record type definition, - the ordering + the ordered and entry order properties of a map have no effect on whether the map matches a particular record type: the entries in a map do not have to be in any particular order.

@@ -19243,24 +19243,17 @@ processing with JSON processing.

see .

-

Maps in &language; have a property called , - which takes three possible values: undefined, sorted, - and insertion. The effect of these three options is explained +

Maps in &language; have a property called , + which takes the value true or false; a map + is accordingly said to be ordered or unordered. + The effect of this property is explained in . In summary:

-

The value undefined means that the order of entries +

In an unordered map, the order of entries in the map is ; it may, for example, be the result of a randomized hashing algorithm.

-

The value sorted means that the map maintains entries - sorted in key order. If this option is chosen then it is required that the - keys be mutually comparable: an error will result if there is a key whose - data type does not define ordering (for example, xs:QName), or if - there are two keys whose data types are not mutually comparable (for example, - xs:integer and xs:string). Strings are sorted - using the Unicode Codepoint Collation.

-

The value insertion means that the map will retain entries - in the order of the initial sequence that results from evaluation of the - contained sequence constructor.

+

In an ordered map, the order of entries is predictable + and depends on the order in which they were added to the map.

@@ -19390,17 +19383,14 @@ processing with JSON processing.

-

The ordering +

The ordered property of a map constructed using a map constructor expression - is undefined.

+ is false.

-

A map with sorted - ordering can be created by applying the map:sort function.

-

A map with insertion - ordering can be created by use of the functions map:build, +

An ordered map can be created by use of the functions map:build, map:merge, or map:of-pairs - with the option { "ordering": "insertion" }.

+ with the option { "retain-order": true() }.

diff --git a/specifications/xquery-40/src/query-prolog.xml b/specifications/xquery-40/src/query-prolog.xml index 5801d19ff..bfb5346f8 100644 --- a/specifications/xquery-40/src/query-prolog.xml +++ b/specifications/xquery-40/src/query-prolog.xml @@ -2139,8 +2139,8 @@ local:depth(doc("partlist.xml"))

So the call cx:complex(3, 2) produces the value { "r": 3e0, "i": 2e0 }, while the call cx:complex(3) produces the value { "r": 3e0, "i": 0e0 }

-

The resulting map has its property set to - , so the order of entries corresponds +

The resulting map has its property set to + true, so the order of entries corresponds to the order of field declarations in the record type. This means, for example, that when the map is serialized using the JSON output method, the order of entries in the output will correspond to the order of field declarations.

diff --git a/specifications/xslt-40/src/element-catalog.xml b/specifications/xslt-40/src/element-catalog.xml index efecf268e..6430afb11 100644 --- a/specifications/xslt-40/src/element-catalog.xml +++ b/specifications/xslt-40/src/element-catalog.xml @@ -1665,11 +1665,9 @@ - + - - - + diff --git a/specifications/xslt-40/src/xslt.xml b/specifications/xslt-40/src/xslt.xml index 4e5b0d646..2a0da8e17 100644 --- a/specifications/xslt-40/src/xslt.xml +++ b/specifications/xslt-40/src/xslt.xml @@ -35620,10 +35620,10 @@ the same group, and the-->

In the absense of duplicate keys, the result of the instruction is then given by the XPath 3.1 expression:

- map:merge($maps, { 'ordering': $ordering }) + map:merge($maps, { 'retain-order': $ordered }) -

where $ordering is the of the ordering - attribute, defaulting to "undefined".

+

where $ordered is the of the ordered + attribute, defaulting to false.

Informally: in the absence of duplicate keys the resulting map contains @@ -35632,26 +35632,21 @@ the same group, and the--> -

The effect of the three different map ordering options is explained +

The effect of the ordered options is explained in . In summary:

-

The value undefined means that the order of entries +

The default value no means that the order of entries in the map is ; it may, for example, be the result of a randomized hashing algorithm.

-

The value sorted means that the map maintains entries - sorted in key order. If this option is chosen then it is required that the - keys be mutually comparable: an error will result if there is a key whose - data type does not define ordering (for example, xs:QName), or if - there are two keys whose data types are not mutually comparable (for example, - xs:integer and xs:string). Strings are sorted - using the Unicode Codepoint Collation.

-

The value insertion means that the map will retain entries - in the order of the initial sequence that results from evaluation of the - contained sequence constructor.

+ +

The value yes means that the order of entries + in the returned map will reflect + the order of items in the sequence that results from evaluation of the + contained sequence constructor; furthermore, the map will have the + property ordered=true, which means that new entries + added using map:put will be added at the end.

-

The selected ordering applies not only to the map that is returned from this - xsl:map instruction, but also to any maps that are subsequently derived - from this by adding or removing entries.

+

The handling of duplicate keys is described in below.

@@ -35660,7 +35655,7 @@ the same group, and the-->

There is no requirement that the supplied input maps should have the same or - compatible types, except for sorted maps where the keys must be comparable. + compatible types. The type of a map (for example map(xs:integer, xs:string)) is descriptive of the entries it currently contains, but is not a constraint on how the map may be combined with other maps.

diff --git a/specifications/xslt-xquery-serialization-40/src/xslt-xquery-serialization.xml b/specifications/xslt-xquery-serialization-40/src/xslt-xquery-serialization.xml index db94b8707..4fd0e8e12 100644 --- a/specifications/xslt-xquery-serialization-40/src/xslt-xquery-serialization.xml +++ b/specifications/xslt-xquery-serialization-40/src/xslt-xquery-serialization.xml @@ -3455,8 +3455,8 @@ The key/value pairs in the serialized output retain the entry order of entries in the map.

The order is implementation-dependent in - the default case where the ordering - property of the map is undefined.

+ the default case where the ordered + property of the map is false.

@@ -23267,7 +23267,6 @@ return fold-left($maps, dm:empty-map($options?ordering otherwise "undefined"), map:merge(({ "red": 0 }, { "green": 1}, { "blue": 2 }), { "retain-order": true() } => map:keys() "red", "green", "blue" - The keys are in first-in, first-out order. @@ -23315,10 +23314,10 @@ return fold-left($maps, dm:empty-map($options?ordering otherwise "undefined"), , retaining their order in the input sequence. - (fn(item()*, item()*) as item()*)? + (fn($existing-value as item()*, $new-value as item()*) as item()*)? fn:op(',') - + @@ -23443,17 +23442,16 @@ map:build($input, map:get(?, 'key'), map:get(?, 'value'), $combine) - map:of-pairs((map:pair("red": 0), map:pair("green": 1), map:pair("blue": 2 )), - { "retain-order": true() } => map:keys() + map:of-pairs((map:pair("red": 0), map:pair("green": 1), map:pair("blue": 2 )) + => map:keys() "red", "green", "blue" The keys are returned in the order supplied. - map:of-pairs((map:pair("red": 0), map:pair("green": 1), map:pair("blue": 2 )), - { "retain-order": true() } => map:put("yellow": -1) => map:keys() + map:of-pairs((map:pair("red": 0), map:pair("green": 1), map:pair("blue": 2 )) + => map:put("yellow": -1) => map:keys() "red", "green", "blue", "yellow" - Because the map is ordered, new entries are added at the end. @@ -23490,22 +23488,16 @@ map:build($input, map:get(?, 'key'), map:get(?, 'value'), $combine)

The number of items in the result will be the same as the number of entries in the map, and the result sequence will contain no duplicate values.

-

If the map is ordered, then the order of the result sequence is predictable and reflects - the order in which entries in the map were added. If the map is unordered, then the order - of the result sequence is .

map:keys({ 1: "yes", 0: "no" }) - (1, 0) - The result is in implementation-dependent order. + (1, 0) - map:keys(map:merge(({"red": 0}, {"blue": 1}, {"green": 2}), {"retain-order": true()})) + map:keys(map:merge(({"red": 0}, {"blue": 1}, {"green": 2}))) ("red", "blue", "green") - The map is ordered, so the order of keys is predictable. @@ -23515,7 +23507,7 @@ map:build($input, map:get(?, 'key'), map:get(?, 'value'), $combine) - + @@ -23563,7 +23555,7 @@ return map:keys-where( fn($key, $value) { $value = ("two", "three") } ) - (2, 3) + (2, 3) @@ -23577,7 +23569,7 @@ return map:keys-where( fn($key, $value) { $value > 5 and $value < 20 } ) - (3, 4) + (3, 4) @@ -23617,7 +23609,7 @@ return map:keys-where($birthdays, fn($name, $date) { focus-independent -

Returns a sequence containing all the values present in a map, in unpredictable order.

+

Returns a sequence containing all the values present in a map, in order.

The function map:items takes any map:items({ 1: "yes", 2: "no" }) - ("yes", "no") - The result is in implementation-dependent order. + ("yes", "no") map:items({ @@ -23644,9 +23634,7 @@ return map:keys-where($birthdays, fn($name, $date) { 2: ("blue", "yellow"), 3: () }) - ("red", "green", "blue", "yellow") - The result is in implementation-dependent order. + ("red", "green", "blue", "yellow") @@ -23689,9 +23677,7 @@ return map:keys-where($birthdays, fn($name, $date) { map:entries( { 1: "yes", 0: "no" } ) - ({ 1: "yes" }, { 0: "no" }) - The result sequence is in implementation-dependent order. + ({ 1: "yes" }, { 0: "no" }) @@ -23735,7 +23721,7 @@ return map:keys-where($birthdays, fn($name, $date) { map:pairs( { 1: "Y", 2: "N" } ) - ({ "key": 1, "value": "Y" }, { "key": 2, "value": "N" }) + ({ "key": 1, "value": "Y" }, { "key": 2, "value": "N" }) @@ -23744,8 +23730,6 @@ return map:keys-where($birthdays, fn($name, $date) { - The result is in implementation-dependent order. @@ -23754,7 +23738,7 @@ return map:keys-where($birthdays, fn($name, $date) { - + @@ -23889,7 +23873,7 @@ return map:keys-where($birthdays, fn($name, $date) { - + @@ -24131,28 +24115,11 @@ declare function map:find($input as item()*, >same key as $key, together with a new entry whose key is $key and whose associated value is $value.

-

The property of the returned map - has the same value as the - property of $map.

-

The entry order - of the entries in the returned map is as follows:

- - -

If $map has ordered=false, then the - entry order is - , and has no necessary relationship with the - entry order of $map.

- -

If $map has ordered=true then:

- -

If $map contains an entry whose key is $key, - then the new value replaces the old value and the position of the entry is not changed.

-

Otherwise, the new entry is added after all existing entries.

-
- -
-
+ of the entries in the returned map is as follows: + if $map contains an entry whose key is $key, + then the new value replaces the old value and the position of the entry is not changed; + otherwise, the new entry is added after all existing entries.

+ - - + + @@ -24737,8 +24626,7 @@ else map:put($map, $key, $action(())) and replaces the entry with this combined value.

-

The $options argument can be used to control the ordering of the result, - and the way in which duplicate keys are handled. +

The $options argument can be used to control the way in which duplicate keys are handled. The option parameter conventions apply. @@ -24752,10 +24640,10 @@ else map:put($map, $key, $action(())) for the same key. The default is to combine the two values using . - (fn(item()*, item()*) as item()*)? + (fn($existing-value as item()*, $new-value as item()*) as item()*)? fn:op(',') - + @@ -24798,8 +24686,7 @@ fold-left($input, {}, fn($map, $item, $pos) { - +

The default function for both $keys and $value is the identity function. Although it is permitted to default both, this serves little purpose: usually at least one of these arguments will be supplied.

@@ -24814,6 +24701,10 @@ fold-left($input, {}, fn($map, $item, $pos) {

fn:concat(?, ",", ?) Form the string-concatenation of the values, comma-separated

fn:op('+') Compute the sum of the values

+

The order of entries in the result reflects + the order of the items in $input from which they were derived. In the + event that two entries have duplicate keys, the position of the combined entry + in the result reflects the position of the first input item with that key.

@@ -34005,9 +33896,8 @@ return $result is derived from V by applying the function derived-value(M', K, V), defined below.

-

The property - and - of M are retained in M'.

+

The + of M is retained in M'.

If $input is an array A, the result is an array A' diff --git a/specifications/xpath-functions-40/src/xpath-functions.xml b/specifications/xpath-functions-40/src/xpath-functions.xml index e7d8bbc5e..a8c10e6e0 100644 --- a/specifications/xpath-functions-40/src/xpath-functions.xml +++ b/specifications/xpath-functions-40/src/xpath-functions.xml @@ -7671,72 +7671,31 @@ return

Ordered maps are introduced. -

A map has a property called ordered, - which takes the value true or false.

- - -

By default, the ordered propery is false, - in which case the map is said to be unordered. The order of entries in an unordered map - is : with many implementations, it is likely - to be entirely unpredictable, based on some internal hashing function applied to the keys.

- -

In a map whose ordered propery is true, - entries in a map are delivered in the order they were added: - new entries are added at the end. The detailed - rules are determined by the map:put function.

-
- -

The entry order of a map +

In 4.0, the entries in a map are ordered. The entry order of a map is referred to as entry order.

-

The entry order of the entries in a map is - respected by functions such as map:entries, - map:keys, map:values, map:pairs, - map:for-each, and - json-to-xml. It also affects the result of the expression - for key $k value $v return EXPR, and the output +

The entry order of the entries in a map is defined by the function or expression + that creates the map, and affects the result of functions and expressions + that process multiple entries in a map, for example the function map:keys + and the expression + for key $k value $v return EXPR. The ordering + is also reflected in the output of the json and adaptive serialization methods.

- -

Ordered maps have two main uses:

- + +

Order is maintained in maps for two main reasons:

-

When a map is constructed in a single operation, for example - by parsing JSON, by converting XML, or by a function such as map:build, - it can be useful if the order of entries in the map retains the order of the - relevant input sequence. For example, there might be no semantic information - in the ordering of a JSON input file, but if a small change is being made to a large - file, then it can be useful if the order of entries in the output is the same as - the order of entries in the input, as this enables easy visual checking that the - change has been made correctly.

-

When a map is constructed incrementally in a sequence of operations, - it can be useful if iterating over the map entries reflects the order in which - the entries were added to the map.

+

To make the representation of a map (such as its JSON + serialization) easier for human readers to process: for example when + visually inspecting the result of a JSON transformation;

+

To make the result of different implementations interoperable.

- -

In the first case the map will typically be constructed using a function such as - map:build, map:of-pairs, or map:merge - with the option { 'retain-order': true() }. - The entry order of the map - will then reflect the order of items in the original input sequence.

- -

In the second case, an empty ordered map will typically be created - using a function call such as map:build({}, { 'retain-order': true() }), - and entries will then be added incrementally by successive calls on map:put, - often within a processing loop controlled using fn:fold-left, - or in XSLT xsl:iterate.

- -

A map constructor expression such as { "first": 1, "second": 2 } - returns a map in which the order of entries in the constructor is lost; this mechanism - cannot therefore be used to construct a map with predictable order of entries. - Instead, the required effect can be achieved with the expression - map:merge(({ "first": 1 }, { "second": 2 }), { 'ordered': true() }).

- - - -

Ordered maps can also be constructed by certain operations such - as parse-json and xml-to-json.

+

Although it is possible to use the ordering of a map to capture + semantic information, the design of functions such as fn:deep-equal + discourages this: maps are compared with each other, and matched against map types, + without regard to the order of entries.

+
- + @@ -7906,9 +7865,6 @@ return
- - - diff --git a/specifications/xquery-40/src/expressions.xml b/specifications/xquery-40/src/expressions.xml index bc7fec356..062fd5ed8 100644 --- a/specifications/xquery-40/src/expressions.xml +++ b/specifications/xquery-40/src/expressions.xml @@ -5408,9 +5408,8 @@ name.

is an instance of K and every value is an instance of V.

-

The ordered - and entry-order - properties of a map have no effect on whether the map matches a particular +

The entry-order + of a map has no effect on whether the map matches a particular map type.

@@ -5617,9 +5616,8 @@ name.

Although constructors for named record types produce a map in which the entry order reflects the order of field definitions in the record type definition, - the ordered - and entry order - properties of a map have no effect on whether the map matches a particular + the entry order + of a map has no effect on whether the map matches a particular record type: the entries in a map do not have to be in any particular order.

@@ -19266,6 +19264,8 @@ processing with JSON processing.

map { 0: false(), 1: true() } can now be written { 0: false(), 1: true() }, provided it is used in a context where this creates no ambiguity. + The order of key-value + pairs in the map constructor is now retained in the constructed map.

A map can be created using a MapConstructor.

@@ -19383,15 +19383,12 @@ processing with JSON processing.

-

The ordered - property of a map constructed using a map constructor expression - is false.

+

The + of the entries in the constructed map retains the order of the + MapConstructorEntry entries + in the input.

+ - -

An ordered map can be created by use of the functions map:build, - map:merge, or map:of-pairs - with the option { "retain-order": true() }.

-
Constructing a fixed map @@ -19979,10 +19976,9 @@ processing with JSON processing.

If KS is a wildcard (*), the result is the same as $V?pairs::(map:keys($V)).

-

The order of entries in the result sequence in this case +

The order of entries in the result sequence reflects the entry order - of the map. In the default case where the map is unordered, - the order of entries in the result sequence is implementation-dependent.

+ of the map.

diff --git a/specifications/xslt-40/src/xslt.xml b/specifications/xslt-40/src/xslt.xml index 2a0da8e17..6b7e726a8 100644 --- a/specifications/xslt-40/src/xslt.xml +++ b/specifications/xslt-40/src/xslt.xml @@ -35620,10 +35620,9 @@ the same group, and the-->

In the absense of duplicate keys, the result of the instruction is then given by the XPath 3.1 expression:

- map:merge($maps, { 'retain-order': $ordered }) + map:merge($maps) + -

where $ordered is the of the ordered - attribute, defaulting to false.

Informally: in the absence of duplicate keys the resulting map contains @@ -35632,21 +35631,9 @@ the same group, and the--> -

The effect of the ordered options is explained - in . In summary:

- -

The default value no means that the order of entries - in the map is ; it may, for example, - be the result of a randomized hashing algorithm.

- -

The value yes means that the order of entries - in the returned map will reflect +

The order of entries in the returned map will reflect the order of items in the sequence that results from evaluation of the - contained sequence constructor; furthermore, the map will have the - property ordered=true, which means that new entries - added using map:put will be added at the end.

-
- + input sequence.

The handling of duplicate keys is described in below.

diff --git a/specifications/xslt-xquery-serialization-40/src/xslt-xquery-serialization.xml b/specifications/xslt-xquery-serialization-40/src/xslt-xquery-serialization.xml index 4fd0e8e12..ee6fefe2f 100644 --- a/specifications/xslt-xquery-serialization-40/src/xslt-xquery-serialization.xml +++ b/specifications/xslt-xquery-serialization-40/src/xslt-xquery-serialization.xml @@ -3454,9 +3454,7 @@ syntax, i.e. {key:value, key:value, ...}. The key/value pairs in the serialized output retain the entry order of entries in the map.

-

The order is implementation-dependent in - the default case where the ordered - property of the map is false.

+ Determines whether special characters are represented in the XDM output in backslash-escaped form. @@ -27558,7 +27556,7 @@ return document { { "x": 2, "y": 5 }.

If duplicate keys are encountered in a JSON object, they are handled as determined by the duplicates option defined above.

-

The order of entries is retained if the retain-order option is set to true.

+

The order of entries is retained.

A JSON array is transformed to an array whose members are the result of converting @@ -27716,8 +27714,8 @@ return document { specification gave the default value as true, but this appears to have been an error, since it was inconsistent with examples given in the specification and with tests in the test suite.

- -

An option is provided to retain the order of entries in maps.

+ +

The order of entries in maps is retained.

diff --git a/specifications/xpath-functions-40/src/xpath-functions.xml b/specifications/xpath-functions-40/src/xpath-functions.xml index a8c10e6e0..8c9372a8c 100644 --- a/specifications/xpath-functions-40/src/xpath-functions.xml +++ b/specifications/xpath-functions-40/src/xpath-functions.xml @@ -7668,7 +7668,7 @@ return
Ordering of Maps - Ordered maps are introduced. + Ordered maps are introduced.

In 4.0, the entries in a map are ordered. The entry order of a map @@ -7780,7 +7780,7 @@ return

Formal Specification of Maps

The XDM data model () defines three primitive operations on maps:

-

dm:empty-map constructs an empty map with a given ordering property.

+

dm:empty-map constructs an empty map.

dm:map-put adds or replaces an entry in a map.

dm:iterate-map applies a supplied function to every entry in a map.

@@ -7792,7 +7792,7 @@ return
to be specified by reference to this function library, without risk of circularity.

There is one exception to this rule: for convenience, the notation {} is used to represent - an empty map, in preference to a call on dm:empty-map(ordering := 'undefined').

+ an empty map, in preference to a call on dm:empty-map().

The formal equivalents are not intended to provide a realistic way of implementating the functions (in particular, any real implementation might be expected to implement map:get diff --git a/specifications/xquery-40/src/expressions.xml b/specifications/xquery-40/src/expressions.xml index 062fd5ed8..231a4e56a 100644 --- a/specifications/xquery-40/src/expressions.xml +++ b/specifications/xquery-40/src/expressions.xml @@ -19216,7 +19216,7 @@ processing with JSON processing.

Maps - Ordered maps are introduced. + Ordered maps are introduced.

@@ -19241,18 +19241,11 @@ processing with JSON processing.

see .

-

Maps in &language; have a property called , - which takes the value true or false; a map - is accordingly said to be ordered or unordered. +

Maps in &language; are ordered. The effect of this property is explained - in . In summary:

- -

In an unordered map, the order of entries - in the map is ; it may, for example, - be the result of a randomized hashing algorithm.

-

In an ordered map, the order of entries is predictable - and depends on the order in which they were added to the map.

-
+ in . + In an ordered map, the order of entries is predictable + and depends on the order in which they were added to the map.

@@ -19264,7 +19257,7 @@ processing with JSON processing.

map { 0: false(), 1: true() } can now be written { 0: false(), 1: true() }, provided it is used in a context where this creates no ambiguity. - The order of key-value + The order of key-value pairs in the map constructor is now retained in the constructed map. @@ -20600,13 +20593,12 @@ return $array?[count(.) ge 2] for each entry in the map, with the context value set to an item of type record(key as xs:anyAtomicType, value as item()*), in which the key and value fields represent the key and value of the map entry. - The context position is the position of the entry in the map (in an arbitrary ordering), + The context position is the position of the entry in the map + (in ), and the context size is the number of entries in the map. The result of the expression is a map containing those entries of the input map for which the of the FILTER expression is true. - The ordered property of the result is the same as the ordered - property of the input map, and in the case of an ordered map, the relative order of - entries in the result retains the relative order of entries in the input. + The relative order of entries in the result retains the relative order of entries in the input.

For example, the following expression:

@@ -20619,11 +20611,9 @@ return $map?[?key ge 2] { 2: "beta", 3: "gamma" } -

Filtering of maps based on numeric positions is not generally useful when - the map is unordered, because the order of entries is unpredictable; but it is available - in the interests of orthogonality.

-

With an ordered map, a filter expression such as $map?[last()-1, last()] - might be used to return the last two entries.

+

A filter expression such as $map?[last()-1, last()] + might be used to return the last two entries of a map in + .

diff --git a/specifications/xslt-40/src/xslt.xml b/specifications/xslt-40/src/xslt.xml index 6b7e726a8..d545fef5e 100644 --- a/specifications/xslt-40/src/xslt.xml +++ b/specifications/xslt-40/src/xslt.xml @@ -35595,9 +35595,9 @@ the same group, and the--> now raises error XTSE3185 (rather than XTSE3280) if both a select attribute and a sequence constructor are present.
- - - Ordered maps are introduced. + + Ordered maps are introduced. +

Two instructions are added to XSLT to facilitate the construction of maps.

diff --git a/specifications/xslt-xquery-serialization-40/src/xslt-xquery-serialization.xml b/specifications/xslt-xquery-serialization-40/src/xslt-xquery-serialization.xml index ee6fefe2f..157daef61 100644 --- a/specifications/xslt-xquery-serialization-40/src/xslt-xquery-serialization.xml +++ b/specifications/xslt-xquery-serialization-40/src/xslt-xquery-serialization.xml @@ -3408,6 +3408,9 @@ is described in .

Added the json-lines parameter for JSON serialization. + + The serialization of maps retains the order of entries. +

The JSON output method serializes the @@ -3727,6 +3730,12 @@ according to the format and as described in Adaptive Output Method + + + + The serialization of maps retains the order of entries. + +

The Adaptive output method serializes the into a human readable form for the purposes of debugging query results. From 4301c5467495cfec40f4256c038122044093566e Mon Sep 17 00:00:00 2001 From: Michael Kay Date: Wed, 22 Jan 2025 17:00:27 +0000 Subject: [PATCH 18/18] Apply post-acceptance changes from review --- .../src/xpath-datamodel.xml | 2 +- .../src/function-catalog.xml | 27 ++++++++++++++----- specifications/xquery-40/src/query-prolog.xml | 14 ++++------ 3 files changed, 27 insertions(+), 16 deletions(-) diff --git a/specifications/xpath-datamodel-40/src/xpath-datamodel.xml b/specifications/xpath-datamodel-40/src/xpath-datamodel.xml index 1753e6acc..cbf407236 100644 --- a/specifications/xpath-datamodel-40/src/xpath-datamodel.xml +++ b/specifications/xpath-datamodel-40/src/xpath-datamodel.xml @@ -766,7 +766,7 @@ therefore can also be contained within sequences.

The dm:iterate-sequence accessor calls the supplied $action function once for each item in $input, in order, - and returns the sequence concenation of the results. The $action function + and returns the sequence concatenation of the results. The $action function is called with two arguments. The first argument is an item in $input, and the second is the 1-based ordinal position of the item within $input.

diff --git a/specifications/xpath-functions-40/src/function-catalog.xml b/specifications/xpath-functions-40/src/function-catalog.xml index c84649fd4..9e3e0f5e2 100644 --- a/specifications/xpath-functions-40/src/function-catalog.xml +++ b/specifications/xpath-functions-40/src/function-catalog.xml @@ -23103,7 +23103,7 @@ xs:QName('xs:double')