Bug #4552
closed

Incorrect output for streamed xsl:message call
100%
Description
Test case si-message-002 is failing on the 10.1 development branch. The test succeeds in 9.9 and 10.0. It's not clear what has changed.
The first symptom is that 9.9 outputs the warning:
Warning on line 28 column 92 of si-message-A.xsl:
SXST0067: Execution of xsl:message is not fully streamed
whereas 10.1 is outputting
Warning on line 28 of si-message-A.xsl:
SXST0067 Execution of consume(consume(((account/transaction[@value lt 0])/@value,
...)!.)) is not fully streamed
Updated by Michael Kay over 3 years ago
- Status changed from New to Resolved
- Priority changed from Low to Normal
- Applies to branch 10 added
- Fix Committed on Branch 10 added
The difference in warning messages is spurious: it only occurs because I was running the tests with export:on. But the failure also occurs with export:off.
The relevant change seems to be a change to Message.java
for bug #4506, which changed the evaluation of xsl:message
from pull mode to push mode.
The problem here is that Expression.process() uses the expression's evaluateItem()
method if getImplementationMethod()
includes Expression.EVALUATE
, which class ConsumingOperand
does; this is only suitable when the expression returns a singleton, and if used in other cases it truncates the sequence to a single item, which is what we see happening.
There are other expression classes that support Expression.EVALUATE
even though they might evaluate to a sequence. But others are more careful: for example CardinalityChecker
has the logic:
public int getImplementationMethod() {
int m = ITERATE_METHOD | PROCESS_METHOD | ITEM_FEED_METHOD;
if (!Cardinality.allowsMany(requiredCardinality)) {
m |= EVALUATE_METHOD;
}
return m;
}
I think the safest thing to do, however, is for Expression.process()
to only use the evaluateItem()
method after doing a cardinality check on the expression.
Updated by Michael Kay over 3 years ago
- Status changed from Resolved to In Progress
Reopening. The fix caused a regression: test math-1201 (when run with -export:on) fails
java.lang.AssertionError: process() is not implemented in the subclass class net.sf.saxon.expr.NegateExpression
The code for a unary minus expression uses a defaulted method to compute the cardinality of the expression: specifically, it returns the cardinality of the operand expression. So the computed cardinality for -child::price
might be zero-or-more. But actually a unary minus expression can only ever return a singleton.
If we evaluate this expression in push mode (e.g because it appears as the body of an element constructor) then we first try the evaluateItem() method, but we're rejecting that because of the incorrect cardinality.
Updated by Michael Kay over 3 years ago
- Status changed from In Progress to Resolved
Two parts to fixing this.
First, NegateExpression (which implements unary minus) should return a static cardinality of (0 or 1).
Secondly, the new fallback code for Expression.process() should be made more robust. There must be either an evaluateItem() method or an iterate() method or both; if both are available then the one we choose should depend on the static cardinality.
Committed these additional changes.
Updated by O'Neil Delpratt over 3 years ago
- % Done changed from 0 to 100
- Fixed in Maintenance Release 10.1 added
Bug fix committed in the Saxon 10.1 maintenance release.
Updated by O'Neil Delpratt over 3 years ago
- Status changed from Resolved to Closed
Please register to edit this issue