2

Example XQuery (using Saxon-HE, version 9.8.0.6)

xquery version "3.1";
let $xml := <simple>
  <hello>Hello World!</hello>
</simple>
return fn:serialize(map{
  'greeting': data($xml/hello),
  'number': data($xml/number)  (: ? how to add this entry only if there is a number ? :)
}, map{'method':'json', 'indent':true()})

Output:

{
  "number":null,
  "greeting":"Hello World!"
}

Question

How to prevent entries with a null value (in this case 'number')? Or more specifically in this case: how to add the 'number' entry only if it is a number?

Note: I know about map:entry and map:merge. I am looking for a solution without these functions, so "inline" (within the map constructor).

Update

Based on the answer of @joewiz, this is not possible. This is the closest we can get:

xquery version "3.1";
declare namespace map="http://www.w3.org/2005/xpath-functions/map";
let $xml := <simple>
  <hello>Hello World!</hello>
</simple>
return fn:serialize(
  map:merge((
    map:entry('greeting', data($xml/hello)),
    let $n := number($xml/number) return if ($n) then map:entry('number', $n) else()
  )),
  map{'method':'json', 'indent':true()})
rmuller
  • 12,062
  • 4
  • 64
  • 92

2 Answers2

5

If you're doing this often enough to make it worthwile you could do:

declare function f:addConditionally($map, $key, $data) as map(*) {
  if (exists($data)) then map:put($map, $key, $data) else $map
};

let $m :=
  map{}
  => f:addConditionally('greeting', data($xml/hello))
  => f:addConditionally('number', data($xml/number))
Michael Kay
  • 156,231
  • 11
  • 92
  • 164
2

According to the XQuery 3.1 specification on Map Constructors, map constructors consist of map constructor entries, which themselves consist of a map key expression and a map value expression. In other words, map constructor entries are not general expressions and cannot accommodate a conditional expression such as:

map { if ($condition) then "key": "value" else () }

If you need to put anything in a map besides a key-value expression pair, you'll need to abandon the map constructor and fall back on map:merge() and map:entry(). The correct syntax for the above case would be as follows:

map:merge( if ($condition) then map:entry("key", "value") else () )
Joe Wicentowski
  • 5,159
  • 16
  • 26