XQuery 3:有条件地添加地图条目

时间:2017-11-09 11:43:02

标签: saxon xquery-3.0

示例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值的条目(在本例中为“数字”)?或者更具体地说,在这种情况下:如果只是一个数字,如何添加“数字”条目?

注意:我了解map:entrymap:merge。我正在寻找没有这些函数的解决方案,所以“内联”(在地图构造函数中)。

更新

根据@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()})

2 个答案:

答案 0 :(得分:3)

如果你经常做这件事,那么你可以做到这一点:

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

答案 1 :(得分:1)

根据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 () )