Hi Jan,
welcome, too.
As Dirk already stated, the behavior of BaseX is correct and compliant with the spec. I’ll try to give you some more hints on what’s going on:
In the first case the expression self::match seems to evaluate to two nodes each of which is passed on to the string() function. Producing two strings in total.
Exactly.
Why should the expression self::match evaluate differently when directly passed to the string function as in the second case?
The string function will be called three times (once for each node). These are the function calls and results:
string(<match>foo</match>) → 'foo' string( () ) → '' string(<match>bar</match>) → 'bar'
And if it actually should evaluate to a sequence of three entries where the second entry is the empty sequence why should the string function evaluate this at all.
Because that’s the way how the string() function has been specified [1]: "$arg as item()?" means that the argument can be an empty sequence.
[…] how function calls inside a path expression should work. I couldn't find anything about that in the xquery specs.
Paths consist of several steps. Each step can be an arbitrary XQuery expression, including function calls. The results of a step will be bound to the context item one by one before the next step is evaluated. This is why e. g. the following query yields <c/>…
<a/>/<b/>/<c/>
…and all of the following queries yield (1, 1):
(<a/>, <b/>)/1 (<a/>, <b/>)/count(.) (<a/>, <b/>)/(let $i := . return count($i))
For more details on paths and steps, you could check out Section 3.3 of the XQuery specification (it’s probably more comprehensive than you’d like it to be…) [2].
Does this answer your question? Christian
[1] http://www.w3.org/TR/xpath-functions-30/#func-string [2] http://www.w3.org/TR/xquery-30/#id-path-expressions