Dear basex people,
I am new to this mailing list. So 'hello' first of all.
In my understanding of xquery the following expressions should be equivalent
/self::match/string()
/string(self::match)
But running
xquery count((<match>foo</match>, <test>test</test>, <match>bar</match>)/self::match/string())
xquery count((<match>foo</match>, <test>test</test>, <match>bar</match>)/string(self::match))
in basex version 7.7.2 turns out to have different results (2 in the first case, 3 in the second). I think it should be 2 in both cases.
This bug was found using functx:get-matches() which doesn't return the expected results in basex.
Best regards. Jan
Hello Jan
On 26/02/14 18:23, Jan Techter wrote:
Dear basex people,
I am new to this mailing list. So 'hello' first of all.
Hello to you, too :) Always happy to have new users.
In my understanding of xquery the following expressions should be equivalent
/self::match/string()
/string(self::match)
But running
xquery count((<match>foo</match>, <test>test</test>, <match>bar</match>)/self::match/string())
xquery count((<match>foo</match>, <test>test</test>, <match>bar</match>)/string(self::match))
I don't think these two expressions are the same and hence this does not seem to be a bug. According to the spec, string($arg) returns a zero length string, if $arg is an empty sequence. As self::match will return an empty sequence for the second element in the sequence (the <test /> element), this will result to a string and thus will be counted in the resulting expression.
Hope this helps.
Cheers, Dirk
On 02/26/2014 06:35 PM, Dirk Kirsten wrote:
Hello Jan
On 26/02/14 18:23, Jan Techter wrote:
Dear basex people,
I am new to this mailing list. So 'hello' first of all.
Hello to you, too :) Always happy to have new users.
In my understanding of xquery the following expressions should be equivalent
/self::match/string()
/string(self::match)
But running
xquery count((<match>foo</match>, <test>test</test>, <match>bar</match>)/self::match/string())
xquery count((<match>foo</match>, <test>test</test>, <match>bar</match>)/string(self::match))
I don't think these two expressions are the same and hence this does not seem to be a bug. According to the spec, string($arg) returns a zero length string, if $arg is an empty sequence. As self::match will return an empty sequence for the second element in the sequence (the <test /> element), this will result to a string and thus will be counted in the resulting expression.
Hope this helps.
Cheers, Dirk
Hi Dirk,
thank you for your immediate reply. I think this is not just about the specs of the string function but about how function calls inside a path expression should work. I couldn't find anything about that in the xquery specs. Maybe somebody could point me to the right section there.
My knowledge about xquery comes mainly from the book XQuery from Priscilla Walmsley who also wrote most of the functx functions. But functx:get-matches() doesn't work as expected in the basex implementation of xquery since she uses the second kind of expression above. In basex this produces a list with more entries than actual matches.
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.
Why should the expression self::match evaluate differently when directly passed to the string function as in the second case? 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. Since it only takes single values.
So if the second expression evaluates at all it seems to me that the only sensible way is to make it equivalent to the first expression.
But maybe the specifications state something different which i am not aware of?
Best, Jan
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
Hi Christian,
now I got it. Your hints have been very helpful in understanding this behavior. And yes, this does answer my question.
Thanks, Jan
On 02/26/2014 11:10 PM, Christian Grün wrote:
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
basex-talk@mailman.uni-konstanz.de