tags:

views:

85

answers:

1

Basically I have several sequences that may be empty, if they are empty then I don't want to output it's parent node. If all of the sequences are empty then I don't want the containing node. Basically I have code similiar to this, which doesn't work:

let $a := //a
let $b := //b

return
<root>
   {if (exists($a) or exists($b)) then
      <div id="container">
         {if (exists($a)) then
            <h2>As</h2>
            <div>
               {for loop for $a sequence...}
            </div>
          else()
          }
          {if (exists($b)) then
            <h2>Bs</h2>
            <div>
               {for loop for $b sequence...}
            </div>
          else()
          }
      </div>
    else()
    }
</root>
A: 

You have a simple syntax error in your query:

if (exists($a))
then
  <h2>As</h2>
  <div>
     {for loop for $a sequence...}
  </div>
else
  ()

The then clause must be an XQuery expression, but here you have two XQuery expressions, the <h2> node and the <div> node.

Returning a sequence of nodes fixes this:

if (exists($a))
then
  (<h2>As</h2>, 
   <div>
     {for loop for $a sequence...}
   </div>)
else
  ()

There is a neat trick you can use to tidy up the query somewhat. The expresion if (exists(A)) then B else () is equivalent to if (A) then B else (), since a call to boolean is introduced around the predicate. This in turn is equivalent to just B[A], as the A predicate can be hoisted.

Using this trick, the query can be written more concisely as:

let $a := //a
let $b := //b
return
<root>
{
  <div id="container">
  {
    (<h2>As</h2>, 
     <div>
     {
       ...
     }
     </div>)[$a],

    (<h2>Bs</h2>,
     <div>
     {
       ...
     }</div>)[$b])
  }
  </div>[$a or $b]
}
</root>
Oliver Hallam
Thank you very much for the solution. Your predicate trick is indeed very slick thanks for sharing that. Though in eXist DB 1.4 a non-empty sequence doesn't return true on it's own. You have to call exists() on it.
Skags