XQuery 3:有条件地添加映射条目

XQuery 3: Conditionally add map entry

XQuery 示例(使用 Saxon-HE,版本 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()})

输出:

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

问题

如何防止具有 null 值的条目(在本例中为 'number')?或者更具体地说,在这种情况下:如何仅在 'number' 条目是数字时添加它?

注意:我知道 map:entrymap:merge。我正在寻找没有这些功能的解决方案,所以 "inline"(在地图构造函数中)。

更新

根据@joewiz 的回答,这是不可能的。这是我们能得到的最接近的:

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()})

根据 Map Constructors 上的 XQuery 3.1 规范,映射构造函数由映射构造函数条目组成,它们本身由映射键表达式和映射值表达式组成。换句话说,映射构造函数条目不是通用表达式,不能容纳条件表达式,例如:

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

如果除了键值表达式对之外还需要在映射中放置任何内容,则需要放弃映射构造函数并转而使用 map:merge()map:entry()。上述情况的正确语法如下:

map:merge( if ($condition) then map:entry("key", "value") else () )

如果你这样做的频率足够高,值得这样做,你可以这样做:

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))