Difference between revisions of "Map Module"

From BaseX Documentation
Jump to navigation Jump to search
m (Text replacement - "</syntaxhighlight>" to "</pre>")
 
(163 intermediate revisions by 6 users not shown)
Line 1: Line 1:
<p>This module contains [[Querying#Functions|XQuery Functions]] for manipulating maps.</p>
+
This [[Module Library|XQuery Module]] contains functions for manipulating maps. [[XQuery 3.1#Maps|Maps]] have been introduced with [[XQuery 3.1]].
<p>All functions are preceded by the <code>map:</code> prefix, which is linked to the <code>http://www.w3.org/2005/xpath-functions/map</code> namespace.</p>
+
 
<p>A map is an additional kind of item.</p>
+
=Conventions=
<p>A map comprises a collation and a set of entries. Each entry comprises a key which is an arbitrary atomic value, and an arbitrary sequence called the associated value. Within a map, no two entries have the same key, when compared using the <code>eq</code> operator under the map's collation. It is not necessary that all the keys should be mutually comparable (for example, they can include a mixture of integers and strings). Key values will never be of type <code>xs:untypedAtomic</code>, and they will never be the <code>xs:float</code> or <code>xs:double</code> value <code>NaN</code>.</p> <p>The function call <code>map:get($map, $key)</code> can be used to retrieve the value associated with a given key.</p>
+
 
<p>A <em>map</em> can also be viewed as a function from keys to associated values. To achieve this, a map is also a function item. The function corresponding to the map has the signature <code>function($key as xs:anyAtomicType) as item()*</code>. Calling the function has the same effect as calling the <code>get</code> function: the expression <code>$map($key)</code> returns the same result as <code>get($map, $key)</code>. For example, if <code>$books-by-isbn</code> is a map whose keys are ISBNs and whose assocated values are <code>book</code> elements, then the expression <code>$books-by-isbn("0470192747")</code> returns the <code>book</code> element with the given ISBN. 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.</p>
+
All functions in this module are assigned to the <code><nowiki>http://www.w3.org/2005/xpath-functions/map</nowiki></code> namespace, which is statically bound to the {{Code|map}} prefix.<br/>
<p>Like all other values, <em>maps</em> are immutable. For example, the <code>map:remove</code> function creates a new map by removing an entry from an existing map, but the existing map is not changed by the operation.</p>
+
 
<p>Like sequences, <em>maps</em> have no identity. It is meaningful to compare the contents of two maps, but there is no way of asking whether they are "the same map": two maps with the same content are indistinguishable.</p>
+
=Functions=
<p>Because a map is a function item, functions that apply to functions also apply to maps. A map is an anonymous function, so <code>fn:function-name</code> returns the empty sequence; <code>fn:arity</code> always returns <code>1</code>.</p>
+
 
<p>Maps may be compared using the <code>fn:deep-equal</code> function. The semantics for this function are extended so that when two items are compared, at any level of recursion, the items compare equal if they are both maps, if both use the same collation, if both contain the same set of keys (compared using the <code>eq</code> operator), without regard to ordering, and if for each key that is present in both maps, the associated values are deep-equal. When comparing maps, the maps' collation is used rather than the collation supplied as an argument to the <code>fn:deep-equal</code> function.</p>
+
Some examples use the ''map'' {{Code|$week}} defined as:
<p>There is no operation to atomize a map or convert it to a string.</p>
+
<pre lang='xquery'>
 +
declare variable $week := map {
 +
  0: "Sun", 1: "Mon", 2: "Tue", 3: "Wed", 4: "Thu", 5: "Fri", 6: "Sat"
 +
};
 +
</pre>
  
==map:collation==
 
{|
 
| width='90' valign='top' | '''Signatures'''
 
| <code><strong>map:collation</strong>($map as map(*)) as xs:string</code><br/>
 
|-
 
| valign='top' | '''Summary'''
 
| <p>Returns the URI of the supplied map's collation.</p>
 
|-
 
| valign='top' | '''Rules'''
 
| The function <code>map:collation</code> returns the collation URI of the <em>map</em> supplied as <code>$input</code>.
 
|}
 
 
==map:contains==
 
==map:contains==
{|
+
 
| width='90' valign='top' | '''Signatures'''
+
{| width='100%'
| <code><strong>map:contains</strong>($map as map(*), $key as item()) as xs:boolean</code><br/>
+
| width='120' | '''Signature'''
|-
+
|<pre>map:contains(
| valign='top' | '''Summary'''
+
  $map as map(*),
| <p>Tests whether a supplied map contains an entry for a given key.</p>
+
  $key as xs:anyAtomicType
|-
+
) as xs:boolean</pre>
| valign='top' | '''Rules'''
+
|- valign="top"
| The function <code>map:contains</code> returns true if the <em>map</em> supplied as <code>$map</code> contains an entry with a key equal to the supplied value of <code>$key</code>; otherwise it returns false. The equality comparison uses the map's collation; no error occurs if the map contains keys that are not comparable with the supplied <code>$key</code>.
+
| '''Summary'''
If the supplied key is <code>xs:untypedAtomic</code>, it is converted to <code>xs:string</code>. If the supplied key is the <code>xs:float</code> or <code>xs:double</code> value <code>NaN</code>, the function returns false.
+
| Returns true if the supplied {{Code|$map}} contains an entry with a key equal to the supplied value of {{Code|$key}}; otherwise it returns false. No error is raised if the map contains keys that are not comparable with the supplied {{Code|$key}}.
<pre class="brush:xquery">let $week := map{0:="Sonntag", 1:="Montag", 2:="Dienstag", 3:="Mittwoch",
+
If the supplied key is {{Code|xs:untypedAtomic}}, it is compared as an instance of {{Code|xs:string}}. If the supplied key is the {{Code|xs:float}} or {{Code|xs:double}} value {{Code|NaN}}, the function returns true if there is an entry whose key is {{Code|NaN}}, or false otherwise.
                4:="Donnerstag", 5:="Freitag", 6:="Samstag"}</pre>
+
|- valign="top"
|-
+
| '''Examples'''
| valign='top' | '''Examples'''
+
|  
|
+
* {{Code|map:contains($week, 2)}} returns {{Code|true()}}.
The expression <code>map:contains($week, 2)</code> returns <code>true()</code>.<br/>
+
* {{Code|map:contains($week, 9)}} returns {{Code|false()}}.
The expression <code>map:contains($week, 9)</code> returns <code>false()</code>.<br/>
+
* <code>map:contains(map {}, "xyz")</code> returns {{Code|false()}}.
The expression <code>map:contains(map{}, "xyz")</code> returns <code>false()</code>.<br/>
+
* <code>map:contains(map { "xyz": 23 }, "xyz")</code> returns {{Code|true()}}.
The expression <code>map:contains(map{"xyz":=23}, "xyz")</code> returns <code>true()</code>.<br/>
 
 
|}
 
|}
 +
 
==map:entry==
 
==map:entry==
{|
 
| width='90' valign='top' | '''Signatures'''
 
| <code><strong>map:entry</strong>($key as item(), $value as item()*) as map(*)</code><br/>
 
|-
 
| valign='top' | '''Summary'''
 
| <p>The function <code>map:entry</code> returns a new <em>map</em> containing a single entry. The collation of the new map is the the default collation from the static context. The key of the entry in the new map is <code>$key</code>, and its associated value is <code>$value</code>.</p>
 
|-
 
| valign='top' | '''Rules'''
 
| If the supplied key is <code>xs:untypedAtomic</code>, it is converted to <code>xs:string</code>. If the supplied key is the <code>xs:float</code> or <code>xs:double</code> value <code>NaN</code>, the supplied <code>$map</code> is returned unchanged.
 
The function <code>map:entry</code> is intended primarily for use in conjunction with the function <code>map:new</code>. For example, a map containing seven entries may be constructed like this:
 
  
<pre class="brush:xquery">
+
{| width='100%'
map:new((
+
| width='120' | '''Signature'''
   map:entry("Su", "Sunday"),
+
|<pre>map:entry(
   map:entry("Mo", "Monday"),
+
  $key    as xs:anyAtomicType,
   map:entry("Tu", "Tuesday"),
+
  $value  as item()*
   map:entry("We", "Wednesday"),
+
) as map(*)</pre>
   map:entry("Th", "Thursday"),
+
|- valign="top"
   map:entry("Fr", "Friday"),
+
| '''Summary'''
   map:entry("Sa", "Saturday")
+
| Creates a new ''map'' containing a single entry. The key of the entry in the new map is {{Code|$key}}, and its associated value is {{Code|$value}}.
 +
The function {{Code|map:entry}} is intended primarily for use in conjunction with the function <code>{{Function||map:merge}}</code>. For example, a map containing seven entries may be constructed like this:
 +
 
 +
<pre lang='xquery'>
 +
map:merge((
 +
   map:entry("Sun", "Sunday"),
 +
   map:entry("Mon", "Monday"),
 +
   map:entry("Tue", "Tuesday"),
 +
   map:entry("Wed", "Wednesday"),
 +
   map:entry("Thu", "Thursday"),
 +
   map:entry("Fri", "Friday"),
 +
   map:entry("Sat", "Saturday")
 
))
 
))
 
</pre>
 
</pre>
  
Unlike the <code>map{...}</code> expression, this technique can be used to construct a map with a variable number of entries, for example:
+
Unlike the <code>map { ... }</code> expression, this technique can be used to construct a map with a variable number of entries, for example:
<pre class="brush:xquery">map:new(for $b in //book return map:entry($b/isbn, $b))</pre>
+
<pre lang='xquery'>map:merge(for $b in //book return map:entry($b/isbn, $b))</pre>
|-
+
|- valign="top"
| valign='top' | '''Examples'''
+
| '''Examples'''
| The expression <code>map:entry("M", "Monday")</code> returns <code>map{"M":="Monday"}</code>.
+
|{{Code|map:entry("M", "Monday")}} creates <code>map { "M": "Monday" }</code>.
 +
|}
 +
 
 +
==map:find==
 +
 
 +
{| width='100%'
 +
| width='120' | '''Signature'''
 +
|<pre>map:find(
 +
  $input  as item()*,
 +
  $key    as xs:anyAtomicType
 +
) as array(*)</pre>
 +
|- valign="top"
 +
| '''Summary'''
 +
| Returns all values of maps in the supplied {{Code|$input}} with the specified {{Code|$key}}. The found values will be returned in an array. Arbitrary input will be processed recursively as follows:
 +
* In a sequence, each item will be processed in order.
 +
* In an array, all array members will be processed as sequence.
 +
* In a map, all entries whose keys match the specified key. Moreover, all values of the map will be processed as sequence.
 +
|- valign="top"
 +
| '''Examples'''
 +
|
 +
* <code>map:find(map { 1:2 }, 1)</code> returns <code>[ 2 ]</code>.
 +
* <code>map:find(map { 1: map { 2: map { 3: 4 } } }, 3)</code> returns <code>[ 4 ]</code>.
 +
* <code>map:find((1, 'b', true#0), 1)</code> returns an empty array.
 +
|}
 +
 
 +
==map:for-each==
 +
 
 +
{| width='100%'
 +
| width='120' | '''Signature'''
 +
|<pre>map:for-each(
 +
  $map    as map(*),
 +
  $action  as function(xs:anyAtomicType, item()*) as item()*
 +
) as item()*</pre>
 +
|- valign="top"
 +
| '''Summary'''
 +
|Applies the specified {{Code|$action}} to every key/value pair of the supplied {{Code|$map}} and returns the results as a sequence.
 +
|- valign="top"
 +
| '''Examples'''
 +
|The following query adds the keys and values of all map entries and returns {{Code|(3,7)}}:
 +
<pre lang='xquery'>
 +
map:for-each(
 +
  map { 1: 2, 3: 4 },
 +
  function($key, $value) { $key + $value }
 +
)
 +
</pre>
 
|}
 
|}
 +
 
==map:get==
 
==map:get==
{|
+
 
| width='90' valign='top' | '''Signatures'''
+
{| width='100%'
| <code><strong>map:get</strong>($map as map(*), $key as item()) as item()*</code><br/>
+
| width='120' | '''Signature'''
|-
+
|<pre>map:get(
| valign='top' | '''Summary'''
+
  $map as map(*),
| <p>Returns the value associated with a supplied key in a given map.</p>
+
  $key as xs:anyAtomicType
|-
+
) as item()*</pre>
| valign='top' | '''Rules'''
+
|- valign="top"
| The function <code>map:get</code> attempts to find an entry within the <em>map</em> supplied as <code>$input</code> that has a key equal to the supplied value of <code>$key</code>. If there is such  an entry, it returns the associated value; otherwise it returns an empty sequence. The equality comparison uses the map's collation; no error occurs if the map contains keys that are not comparable with the supplied <code>$key</code>. If the supplied key is <code>xs:untypedAtomic</code>, it is converted to <code>xs:string</code>. If the supplied key is the <code>xs:float</code> or <code>xs:double</code> value <code>NaN</code>, the function returns an empty sequence.
+
| '''Summary'''
A return value of <code>()</code> from <code>map:get</code> could indicate that the key is present in the map with an associated value of <code>()</code>, or it could indicate that the key is not present in the map. The two cases can be distinguished by calling <code>map:contains</code>.
+
|Returns the value associated with a supplied key in a given map. This function attempts to find an entry within the {{Code|$map}} that has a key equal to the supplied value of {{Code|$key}}. If there is such  an entry, the function returns the associated value; otherwise it returns an empty sequence. No error is raised if the map contains keys that are not comparable with the supplied {{Code|$key}}. If the supplied key is {{Code|xs:untypedAtomic}}, it is converted to {{Code|xs:string}}.
Invoking the <em>map</em> as a function item has the same effect as calling <code>get</code>: that is, when <code>$map</code> is a map, the expression <code>$map($K)</code> is equivalent to <code>get($map, $K)</code>. Similarly, the expression <code>get(get(get($map, 'employee'), 'name'), 'first')</code> can be written as <code>$map('employee')('name')('first')</code>.
+
A return value of {{Code|()}} from {{Code|map:get}} could indicate that the key is present in the map with an associated value of {{Code|()}}, or it could indicate that the key is not present in the map. The two cases can be distinguished by calling {{Code|map:contains}}.
<pre class="brush:xquery">let $week := map{0:="Sonntag", 1:="Montag", 2:="Dienstag", 3:="Mittwoch",
+
Invoking the ''map'' as a function item has the same effect as calling {{Code|get}}: that is, when {{Code|$map}} is a map, the expression {{Code|$map($K)}} is equivalent to {{Code|get($map, $K)}}. Similarly, the expression {{Code|get(get(get($map, 'employee'), 'name'), 'first')}} can be written as {{Code|$map('employee')('name')('first')}}.
                4:="Donnerstag", 5:="Freitag", 6:="Samstag"}</pre>
+
|- valign="top"
|-
+
| '''Examples'''
| valign='top' | '''Examples'''
+
|
|  
+
* {{Code|map:get($week, 4)}} returns {{Code|"Thu"}}.
The expression <code>map:get($week, 4)</code> returns <code>"Donnerstag"</code>.<br/>
+
* {{Code|map:get($week, 9)}} returns {{Code|()}}. ''(When the key is not present, the function returns an empty sequence.).''
The expression <code>map:get($week, 9)</code> returns <code>()</code>. <em>(When the key is not present, the function returns an empty sequence.).</em><br/>
+
* {{Code|map:get(map:entry(7,())), 7)}} returns {{Code|()}}. ''(An empty sequence as the result can also signify that the key is present and the associated value is an empty sequence.).''
The expression <code>map:get(map:entry(7,())), 7)</code> returns <code>()</code>. <em>(An empty sequence as the result can also signify that the key is present and the associated value is an empty sequence.).</em><br/>
 
 
|}
 
|}
 +
 
==map:keys==
 
==map:keys==
{|
+
 
| width='90' valign='top' | '''Signatures'''
+
{| width='100%'
| <code><strong>map:keys</strong>($map as map(*)) as xs:anyAtomicType*</code><br/>
+
| width='120' | '''Signature'''
|-
+
|<pre>map:keys(
| valign='top' | '''Summary'''
+
  $map as map(*)
| <p>Returns a sequence containing all the key values present in a map.</p>
+
) as xs:anyAtomicType*</pre>
|-
+
|- valign="top"
| valign='top' | '''Rules'''
+
| '''Summary'''
| The function <code>map:keys</code> takes any <em>map</em> as its <code>$input</code> argument and returns the keys that are present in the map as a sequence of atomic values, in implementation-dependent order.
+
|Returns a sequence containing all the key values present in a map. The function takes the supplied {{Code|$map}} and returns the keys that are present in the map as a sequence of atomic values. The order may differ from the order in which entries were inserted in the map.
|-
+
|- valign="top"
| valign='top' | '''Examples'''
+
| '''Examples'''
| The expression <code>map:keys(map{1:="yes", 2:="no"})</code> returns some permutation of <code>(1,2)</code>. <em>(The result is in implementation-dependent order.).</em><br/>
+
|
 +
* <code>map:keys(map { 1: "yes", 2: "no" })</code> returns {{Code|(1,2)}}.
 +
|}
 +
 
 +
==map:merge==
 +
 
 +
{| width='100%'
 +
| width='120' | '''Signature'''
 +
|<pre>map:merge(
 +
  $maps    as map(*)*,
 +
  $options  as map(*)  := map { }
 +
) as map(*)</pre>
 +
|- valign="top"
 +
| '''Summary'''
 +
| Constructs and returns a new map. The ''map'' is formed by combining the contents of the supplied {{Code|$maps}}. The maps are combined as follows:
 +
# There is one entry in the new map for each distinct key present in the union of the input maps.
 +
# The {{Code|$options}} argument defines how duplicate keys are handled. Currently, a single option {{Code|duplicates}} exists, and its allowed values are {{Code|use-first}}, {{Code|use-last}}, {{Code|combine}} and {{Code|reject}} (default: {{Code|use-first}}).
 +
|- valign="top"
 +
| '''Examples'''
 +
|
 +
* {{Code|map:merge(())}} creates an empty map.
 +
* {{Code|map:merge((map:entry(0, "no"), map:entry(1, "yes")))}} creates <code>map { 0: "no", 1: "yes" }</code>.
 +
* The following function adds a seventh entry to an existing map:
 +
<pre lang='xquery'>
 +
map:merge(($week, map { 7: "---" }))
 +
</pre>
 +
* In the following example, the values of all maps are combined, resulting in a map with a single key (<code>map { "key": (1, 2, 3) }</code>):
 +
<pre lang='xquery'>
 +
map:merge(
 +
  for $i in 1 to 3 return map { 'key': $i },
 +
  map { 'duplicates': 'combine' }
 +
)
 +
</pre>
 
|}
 
|}
==map:new==
+
 
{|
+
==map:put==
| width='90' valign='top' | '''Signatures'''
+
 
| <code><strong>map:new</strong>() as map(*)</code><br/><code><strong>map:new</strong>($maps as map(*)*) as map(*)</code><br/><code><strong>map:new</strong>($maps as map(*)*, $coll as xs:string) as map(*)</code><br/>
+
{| width='100%'
|-
+
| width='120' | '''Signature'''
| valign='top' | '''Summary'''
+
|<pre>map:put(
| <p>Creates a new map: either an empty map, or a map that combines entries from a number of existing maps.</p>
+
  $map    as map(*),
|-
+
  $key    as xs:anyAtomicType,
| valign='top' | '''Rules'''
+
  $value  as item()*
| The function <code>map:new</code> constructs and returns a new map. The zero-argument form of the function returns an empty <em>map</em> whose collation is the default collation in the static context. It is equivalent to calling the one-argument form of the function with an empty sequence as the value of the first argument.
+
) as map(*)</pre>
The one-argument form of the function returns a <em>map</em> that is formed by combining the contents of the maps supplied in the <code>$input</code> argument. It is equivalent to calling the two-argument form of the function with the default collation from the static context as the second argument.
+
|- valign="top"
The two-argument form of the function returns a <em>map</em> that is formed by combining the contents of the maps supplied in the <code>$input</code> argument. The collation of the new map is the value of the <code>$collation</code> argument. The supplied maps are combined as follows:
+
| '''Summary'''
<ol>
+
| Creates a new ''map'', containing the entries of the supplied {{Code|$map}} and a new entry composed by {{Code|$key}} and {{Code|$value}}. The semantics of this function are equivalent to <code>map:merge((map { $key, $value }, $map))</code>
  <li>
 
    <p>
 
      There is one entry in the new map for each distinct key value
 
      present in the union of the input maps, where keys are considered
 
      distinct according to the rules of the <code>distinct-values</code>
 
      function with <code>$collation</code> as the collation.
 
    </p>
 
  </li>
 
  <li>
 
    <p>
 
      The associated value for each such key is taken from the last
 
      map in the input sequence <code>$input</code> that contains an
 
      entry with this key. If this map contains more than one entry with
 
      this key (which can happen if its collation is different from that
 
      of the new map) then it is <em>implementation-dependent</em>
 
      which of them is selected.
 
    </p>
 
  </li>
 
</ol>
 
There is no requirement that the supplied input maps should have the same or compatible types. The type of a map (for example <code>map(xs:integer, xs:string)</code>) is descriptive of the entries it currently contains, but is not a constraint on how the map may be combined with other maps.
 
<pre class="brush:xquery">let $week := map{0:="Sonntag", 1:="Montag", 2:="Dienstag",
 
            3:="Mittwoch", 4:="Donnerstag", 5:="Freitag", 6:="Samstag"}</pre>
 
|-
 
| valign='top' | '''Examples'''
 
|
 
The expression <code>map:new()</code> returns <code>map{}</code>. <em>(Returns an empty map, whose collation is the default collation from the static context).</em><br/>
 
The expression <code>map:new(())</code> returns <code>map{}</code>. <em>(Returns an empty map, whose collation is the default collation from the static context).</em><br/>
 
The expression <code>map:new(map:entry(0, "no"), map:entry(1, "yes"))</code> returns <code>map{0:="no", 1:="yes"}</code>. <em>(Returns a map with two entries; the collation of the map is the default collation from the static context).</em><br/>
 
The expression <code>map:new(map:entry(0, "no"), map:entry(1, "yes"))</code> returns <code>map{0:="no", 1:="yes"}</code>. <em>(Returns a map with two entries; the collation of the map is the default collation from the static context).</em><br/>
 
The expression <code>map:new(($week, map{7:="Unbekannt"}))</code> returns <code>map{0:="Sonntag", 1:="Montag", 2:="Dienstag", 3:="Mittwoch", 4:="Donnerstag", 5:="Freitag", 6:="Samstag", 7:="Unbekannt"}</code>. <em>(The value of the existing map is unchanged; a new map is created containing all the entries from <code>$week</code>, supplemented with a new entry.).</em><br/>
 
The expression <code>map:new(($week, map{6:="Sonnabend"}))</code> returns <code>map{0:="Sonntag", 1:="Montag", 2:="Dienstag", 3:="Mittwoch", 4:="Donnerstag", 5:="Freitag", 6:="Sonnabend"}</code>. <em>(The value of the existing map is unchanged; a new map is created containing all the entries from <code>$week</code>, with one entry replaced by a new entry. Both input maps contain an entry with the key value <code>6</code>; the one used in the result is the one that comes last in the input sequence.).</em><br/>
 
The expression <code>map:new((map{"A":=1}, map{"a:=2"}), "http://collation.example.com/caseblind")</code> returns <code>map{"a":=2}</code>. <em>(Assuming that the keys of the two entries are equal under the rules of the chosen collation, only one of the entries can appear in the result; the one that is chosen is the one from the last map in the input sequence. If both entries were in the same map, it would be implementation-dependent which was chosen.).</em><br/>
 
 
|}
 
|}
 +
 
==map:remove==
 
==map:remove==
{|
+
 
| width='90' valign='top' | '''Signatures'''
+
{| width='100%'
| <code><strong>map:remove</strong>($map as map(*), $key as item()) as map(*)</code><br/>
+
| width='120' | '''Signature'''
|-
+
|<pre>map:remove(
| valign='top' | '''Summary'''
+
  $map   as map(*),
| <p>Constructs a new map by removing an entry from an existing map.</p>
+
  $keys  as xs:anyAtomicType*
|-
+
) as map(*)</pre>
| valign='top' | '''Rules'''
+
|- valign="top"
| The function <code>map:remove</code> returns a new <em>map</em>. The collation of the new map is the same as the collation of the map supplied as <code>$map</code>. The entries in the new map correspond to the entries of <code>$map</code>, excluding any entry whose key is equal to <code>$key</code>.
+
| '''Summary'''
No failure occurs if the input map contains no entry with the supplied key; the input map is returned unchanged
+
| Constructs a new map by removing entries from an existing map. The entries in the new map correspond to the entries of {{Code|$map}}, excluding entries supplied via {{Code|$keys}}.
<pre class="brush:xquery">let $week := map{0:="Sonntag", 1:="Montag", 2:="Dienstag",
+
No failure occurs if the input map contains no entry with the supplied keys; the input map is returned unchanged.
            3:="Mittwoch", 4:="Donnerstag", 5:="Freitag", 6:="Samstag"}</pre>
+
|- valign="top"
|-
+
| '''Examples'''
| valign='top' | '''Examples'''
+
|
| The expression <code>map:remove($week, 4)</code> returns <code>map{0:="Sonntag", 1:="Montag", 2:="Dienstag", 3:="Mittwoch", 5:="Freitag", 6:="Samstag"}</code>.<br/>
+
* {{Code|map:remove($week, 4)}} creates <code>map { 0: "Sun", 1: "Mon", 2: "Tue", 3: "Wed", 5: "Fri", 6: "Sat" }</code>.
The expression <code>map:remove($week, 23)</code> returns <code>map{0:="Sonntag", 1:="Montag", 2:="Dienstag", 3:="Mittwoch", 4:="Donnerstag", 5:="Freitag", 6:="Samstag"}</code>.<br/>
+
* {{Code|map:remove($week, 23)}} creates <code>map { 0: "Sun", 1: "Mon", 2: "Tue", 3: "Wed", 4: "Thu", 5: "Fri", 6: "Sat" }</code>.
 
|}
 
|}
 +
 
==map:size==
 
==map:size==
{|
+
 
| width='90' valign='top' | '''Signatures'''
+
{| width='100%'
| <code><strong>map:size</strong>($map as map(*)) as xs:integer</code><br/>
+
| width='120' | '''Signature'''
|-
+
|<pre>map:size(
| valign='top' | '''Summary'''
+
  $map as map(*)
| <p>Returns a the number of entries in the supplied map.</p>
+
) as xs:integer</pre>
|-
+
|- valign="top"
| valign='top' | '''Rules'''
+
| '''Summary'''
| The function <code>map:size</code> takes any <em>map</em> as its <code>$input</code> argument and returns the number of entries that are present in the map.
+
| Returns a the number of entries in the supplied map. The function takes the supplied {{Code|$map}} and returns the number of entries that are present in the map.
|-
+
|- valign="top"
| valign='top' | '''Examples'''
+
| '''Examples'''
| The expression <code>map:size(map:new())</code> returns <code>0</code>.<br/> The expression <code>map:size(map{"true":=1, "false":0})</code> returns <code>2</code>.<br/>
+
|
 +
* {{Code|map:size(map:merge(()))}} returns {{Code|0}}.
 +
* <code>map:size(map { "true": 1, "false": 0 })</code> returns {{Code|2}}.
 
|}
 
|}
 +
 +
=Changelog=
 +
 +
;Version 8.6
 +
* Added: {{Function||map:find}}
 +
* Updated: {{Function||map:merge}}: Signature extended with options argument. By default, value of first key is now adopted (instead of last, as in previous versions).
 +
 +
;Version 8.4
 +
* Removed: map:serialize (use fn:serialize instead)
 +
 +
;Version 8.0
 +
* Added: {{Function||map:for-each}}, {{Function||map:merge}}, {{Function||map:put}}
 +
* Removed: support for collations (in accordance with the XQuery 3.1 spec).
 +
* Removed: {{Code|map:new}} (replaced with {{Code|map:merge}})
 +
* Updated: aligned with latest specification: compare keys of type {{Code|xs:untypedAtomic}} as {{Code|xs:string}} instances, store {{Code|xs:float}} or {{Code|xs:double}} value {{Code|NaN}}.
 +
* Introduction on maps is now found in the article on [[XQuery 3.1#Maps|XQuery 3.1]].
 +
 +
;Version 7.8
 +
* Updated: map syntax <code>map { 'key': 'value' }</code>
 +
* Added: {{Function||map:serialize}}
 +
 +
;Version 7.7.1
 +
* Updated: alternative map syntax without {{Code|map}} keyword and {{Code|:}} as key/value delimiter (e.g.: <code>{ 'key': 'value' })</code>

Latest revision as of 18:33, 1 December 2023

This XQuery Module contains functions for manipulating maps. Maps have been introduced with XQuery 3.1.

Conventions[edit]

All functions in this module are assigned to the http://www.w3.org/2005/xpath-functions/map namespace, which is statically bound to the map prefix.

Functions[edit]

Some examples use the map $week defined as:

declare variable $week := map {
  0: "Sun", 1: "Mon", 2: "Tue", 3: "Wed", 4: "Thu", 5: "Fri", 6: "Sat"
};

map:contains[edit]

Signature
map:contains(
  $map  as map(*),
  $key  as xs:anyAtomicType
) as xs:boolean
Summary Returns true if the supplied $map contains an entry with a key equal to the supplied value of $key; otherwise it returns false. No error is raised if the map contains keys that are not comparable with the supplied $key.

If the supplied key is xs:untypedAtomic, it is compared as an instance of xs:string. If the supplied key is the xs:float or xs:double value NaN, the function returns true if there is an entry whose key is NaN, or false otherwise.

Examples
  • map:contains($week, 2) returns true().
  • map:contains($week, 9) returns false().
  • map:contains(map {}, "xyz") returns false().
  • map:contains(map { "xyz": 23 }, "xyz") returns true().

map:entry[edit]

Signature
map:entry(
  $key    as xs:anyAtomicType,
  $value  as item()*
) as map(*)
Summary Creates a new map containing a single entry. The key of the entry in the new map is $key, and its associated value is $value.

The function map:entry is intended primarily for use in conjunction with the function map:merge. For example, a map containing seven entries may be constructed like this:

map:merge((
  map:entry("Sun", "Sunday"),
  map:entry("Mon", "Monday"),
  map:entry("Tue", "Tuesday"),
  map:entry("Wed", "Wednesday"),
  map:entry("Thu", "Thursday"),
  map:entry("Fri", "Friday"),
  map:entry("Sat", "Saturday")
))

Unlike the map { ... } expression, this technique can be used to construct a map with a variable number of entries, for example:

map:merge(for $b in //book return map:entry($b/isbn, $b))
Examples map:entry("M", "Monday") creates map { "M": "Monday" }.

map:find[edit]

Signature
map:find(
  $input  as item()*,
  $key    as xs:anyAtomicType
) as array(*)
Summary Returns all values of maps in the supplied $input with the specified $key. The found values will be returned in an array. Arbitrary input will be processed recursively as follows:
  • In a sequence, each item will be processed in order.
  • In an array, all array members will be processed as sequence.
  • In a map, all entries whose keys match the specified key. Moreover, all values of the map will be processed as sequence.
Examples
  • map:find(map { 1:2 }, 1) returns [ 2 ].
  • map:find(map { 1: map { 2: map { 3: 4 } } }, 3) returns [ 4 ].
  • map:find((1, 'b', true#0), 1) returns an empty array.

map:for-each[edit]

Signature
map:for-each(
  $map     as map(*),
  $action  as function(xs:anyAtomicType, item()*) as item()*
) as item()*
Summary Applies the specified $action to every key/value pair of the supplied $map and returns the results as a sequence.
Examples The following query adds the keys and values of all map entries and returns (3,7):
map:for-each(
  map { 1: 2, 3: 4 },
  function($key, $value) { $key + $value }
)

map:get[edit]

Signature
map:get(
  $map  as map(*),
  $key  as xs:anyAtomicType
) as item()*
Summary Returns the value associated with a supplied key in a given map. This function attempts to find an entry within the $map that has a key equal to the supplied value of $key. If there is such an entry, the function returns the associated value; otherwise it returns an empty sequence. No error is raised if the map contains keys that are not comparable with the supplied $key. If the supplied key is xs:untypedAtomic, it is converted to xs:string.

A return value of () from map:get could indicate that the key is present in the map with an associated value of (), or it could indicate that the key is not present in the map. The two cases can be distinguished by calling map:contains. Invoking the map as a function item has the same effect as calling get: that is, when $map is a map, the expression $map($K) is equivalent to get($map, $K). Similarly, the expression get(get(get($map, 'employee'), 'name'), 'first') can be written as $map('employee')('name')('first').

Examples
  • map:get($week, 4) returns "Thu".
  • map:get($week, 9) returns (). (When the key is not present, the function returns an empty sequence.).
  • map:get(map:entry(7,())), 7) returns (). (An empty sequence as the result can also signify that the key is present and the associated value is an empty sequence.).

map:keys[edit]

Signature
map:keys(
  $map  as map(*)
) as xs:anyAtomicType*
Summary Returns a sequence containing all the key values present in a map. The function takes the supplied $map and returns the keys that are present in the map as a sequence of atomic values. The order may differ from the order in which entries were inserted in the map.
Examples
  • map:keys(map { 1: "yes", 2: "no" }) returns (1,2).

map:merge[edit]

Signature
map:merge(
  $maps     as map(*)*,
  $options  as map(*)   := map { }
) as map(*)
Summary Constructs and returns a new map. The map is formed by combining the contents of the supplied $maps. The maps are combined as follows:
  1. There is one entry in the new map for each distinct key present in the union of the input maps.
  2. The $options argument defines how duplicate keys are handled. Currently, a single option duplicates exists, and its allowed values are use-first, use-last, combine and reject (default: use-first).
Examples
  • map:merge(()) creates an empty map.
  • map:merge((map:entry(0, "no"), map:entry(1, "yes"))) creates map { 0: "no", 1: "yes" }.
  • The following function adds a seventh entry to an existing map:
map:merge(($week, map { 7: "---" }))
  • In the following example, the values of all maps are combined, resulting in a map with a single key (map { "key": (1, 2, 3) }):
map:merge(
  for $i in 1 to 3 return map { 'key': $i },
  map { 'duplicates': 'combine' }
)

map:put[edit]

Signature
map:put(
  $map    as map(*),
  $key    as xs:anyAtomicType,
  $value  as item()*
) as map(*)
Summary Creates a new map, containing the entries of the supplied $map and a new entry composed by $key and $value. The semantics of this function are equivalent to map:merge((map { $key, $value }, $map))

map:remove[edit]

Signature
map:remove(
  $map   as map(*),
  $keys  as xs:anyAtomicType*
) as map(*)
Summary Constructs a new map by removing entries from an existing map. The entries in the new map correspond to the entries of $map, excluding entries supplied via $keys.

No failure occurs if the input map contains no entry with the supplied keys; the input map is returned unchanged.

Examples
  • map:remove($week, 4) creates map { 0: "Sun", 1: "Mon", 2: "Tue", 3: "Wed", 5: "Fri", 6: "Sat" }.
  • map:remove($week, 23) creates map { 0: "Sun", 1: "Mon", 2: "Tue", 3: "Wed", 4: "Thu", 5: "Fri", 6: "Sat" }.

map:size[edit]

Signature
map:size(
  $map  as map(*)
) as xs:integer
Summary Returns a the number of entries in the supplied map. The function takes the supplied $map and returns the number of entries that are present in the map.
Examples
  • map:size(map:merge(())) returns 0.
  • map:size(map { "true": 1, "false": 0 }) returns 2.

Changelog[edit]

Version 8.6
  • Added: map:find
  • Updated: map:merge: Signature extended with options argument. By default, value of first key is now adopted (instead of last, as in previous versions).
Version 8.4
  • Removed: map:serialize (use fn:serialize instead)
Version 8.0
  • Added: map:for-each, map:merge, map:put
  • Removed: support for collations (in accordance with the XQuery 3.1 spec).
  • Removed: map:new (replaced with map:merge)
  • Updated: aligned with latest specification: compare keys of type xs:untypedAtomic as xs:string instances, store xs:float or xs:double value NaN.
  • Introduction on maps is now found in the article on XQuery 3.1.
Version 7.8
Version 7.7.1
  • Updated: alternative map syntax without map keyword and : as key/value delimiter (e.g.: { 'key': 'value' })