Support #3567
closedError from string-join when moving to Saxon 9.7
0%
Description
We're working on migrating our codebase from 9.5 to 9.7 and we are seeing the following error: "An empty sequence is not allowed as the second argument of _STRING-JOIN_2.0()" This is typically being triggered by invocations of string-join where the second argument is an element which is conditionally available based on context. I've attached a stylesheet which demonstrates the problem. It includes the code that worked in 9.5 and fails in 9.7 as well as a potential fix for 9.7.
My question is whether this change is expected (and thus requires us to update our codebase) or if this is unintended.
Thanks for you help.
Files
Updated by Michael Kay almost 7 years ago
This may be related to bug #2738 - certainly the patch for that bug accounts for the strange function name _STRING-JOIN_2.0() in the error message. However, that bug was all to do with the change in type of the first argument, whereas this error is about the cardinality of the second argument, which hasn't changed.
Updated by Michael Kay almost 7 years ago
It seems to me that the stylesheet code is clearly wrong: if <name>
has no <suffix>
child, then $suffix-join
will be an empty sequence, and the signature of string-join()
does not allow the second argument to be an empty sequence.
So the only question is, why did Saxon 9.5 not report the error?
The answer is that there's no requirement to report an error in respect of a subexpression that isn't evaluated, and there is no necessity to evaluate the second argument of string-join()
unless the first argument is a sequence of 2 or more items. If there is no @@, then the first argument of string-join() will be a singleton string, so the separator is not used. So it's implementation-defined whether the second argument gets evaluated, and therefore whether the error is reported.
In 9.7, in the interests of providing a single implementation of string-join()
that would work in all scenarios (push and pull evaluation, static and dynamic evaluation, streaming and non-streaming), string-join()
and other aggregate functions like avg()
and sum()
were reimplemented using a general higher-order fold()
mechanism, and a side-effect of this change was that the separator is evaluated eagerly. I figured that we could get away with this because evaluation of the separator argument will rarely be expensive (99% of the time it will be a string literal or at worst a variable reference).
So I think the answer is that both releases are conformant, and that the change in behaviour is a consequence of a redesign that is working as intended.
Please register to edit this issue