Why does the first xquery statement work but the second doesn't

Viewed 60

I'm new to xquery. Why does the first xquery statement work but the second doesn't? The first has multiple xml elements at the second level and the first has multiple at the top level.

let $payload := <root><foo>bar</foo></root>

return
<root>
{
    if (exists($payload/foo)) then
        <prop>
        <key>mykey</key>
        <value>bar</value>
        </prop>
    else
        ""
}
</root>

and this doesn't

let $payload := <root><foo>bar</foo></root>

return
<root>
{
    if (exists($payload/foo)) then
        <key>mykey</key>
        <value>bar</value>
    else
        ""
}
</root>
3 Answers

You will need to wrap your element into parentheses and separate the elements with commas as there is no enclosing root element:

    if (exists($payload/foo)) then (
        <key>mykey</key>,
        <value>bar</value>
    ) else (
      ""
    )

A single element constructor is a valid expression:

<key>mykey</key>

A sequence of two element constructors (with no separator) is not:

<key>mykey</key>
<value>bar</value>

Note that this differs from XSLT, where such element constructors (called literal result elements) always appear as part of a "sequence constructor", and a sequence constructor allows multiple elements to appear.

Since you are starting to learn XQuery it might interest you that instead of returning an empty string you can also return an empty sequence instead.

let $payload := <root><foo>bar</foo></root>

return
  <root>
  {
    if (exists($payload/foo))
    then (
        <key>mykey</key>,
        <value>bar</value>
    )
    else ()
  }
  </root>
Related