Error probably related to xsl:for-each-group
Added by Anonymous over 16 years ago
Legacy ID: #5129558 Legacy Poster: Vladimir Nesterovsky (vnesterovsky)
Hello Mr. Kay, I'm dealing with an error that I could not localize for a while, I'm trying however. It looks very strange because it depends on existance of xsl:message instruction. Sorry for the irrelevant code, but it could be important: --- | <xsl:variable name="source" as="element()+"> | <xsl:variable name="into" as="element()" select="$statement/into"/> | <xsl:variable name="where" as="element()?" select="$statement/where"/> | | <xsl:variable name="source-records" as="element()+" | select="$into/entity/p:generate-sources(@view-id, $dvset)"/> | <xsl:variable name="join-records" as="element()*" | select="$where//join/p:generate-read-join-sources(., $dvset)"/> | | <xsl:for-each-group select="$source-records, $join-records" | group-by="xs:string(@view-id)"> | <xsl:for-each-group select="current-group()" | group-by="xs:string(@record-id)"> | <xsl:sequence select="."/> | </xsl:for-each-group> | </xsl:for-each-group> | </xsl:variable> | | <xsl:message select="$source"/> | ... --- A variable $source receives a sequence of elements with distinct pairs (@view-id, @record-id). Whenever I insert xsl:message code works. If I remove it I'm getting an error further in the code, which happens due to the violation of pairs uniquines. I use no extension functions on the way. P.S. I'm using Saxon 9.1
Replies (8)
Please register to reply
RE: Error probably related to xsl:for-each-gr - Added by Anonymous over 16 years ago
Legacy ID: #5129579 Legacy Poster: Michael Kay (mhkay)
Could you please post a complete stylesheet/source document so that I can reproduce the problem and debug it? If the presence of xsl:message affects it, then it's probably an incorrect optimization rewrite, and it could easily be affected by things outside this code fragment. Michael Kay
RE: Error probably related to xsl:for-each-group - Added by Anonymous over 16 years ago
Legacy ID: #5129943 Legacy Poster: Vladimir Nesterovsky (vnesterovsky)
This probably is not the simplest form, but is a good starting point: <?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:d="http://www.bphx.com/coolgen/derived-data/2007-12-12" xmlns="http://www.bphx.com/coolgen/derived-data/2007-12-12" xpath-default-namespace="http://www.bphx.com/coolgen/derived-data/2007-12-12" xmlns:t="http://www.bphx.com/coolgen/public/db2" exclude-result-prefixes="t xs d"> <xsl:template match="/"> <xsl:variable name="records" as="element()+"> <record view-id="2009072185"> <field/> </record> <record view-id="2009072185"> <field/> </record> </xsl:variable> <xsl:variable name="source" as="element()+"> <xsl:for-each-group select="$records" group-by="xs:string(@view-id)"> <xsl:sequence select="."/> </xsl:for-each-group> </xsl:variable> <xsl:message select="$source"/> <xsl:variable name="alias" as="xs:string+"> <xsl:for-each select="$source"> <xsl:choose> <xsl:when test="last() = 1"> <xsl:sequence select="'T'"/> </xsl:when> <xsl:otherwise> <xsl:sequence select="concat('T', position())"/> </xsl:otherwise> </xsl:choose> </xsl:for-each> </xsl:variable> <select> <xsl:for-each select="$source"> <field alias="{$alias}"/> </xsl:for-each> <xsl:variable name="index" as="xs:integer" select=" for $i in 1 to count($source), $source-record in $source[$i][. is $source[1]] return $i"/> <field alias="{$alias[$index]}"/> </select> </xsl:template> </xsl:stylesheet> Thanks.
RE: Error probably related to xsl:for-each-gr - Added by Anonymous over 16 years ago
Legacy ID: #5131403 Legacy Poster: Michael Kay (mhkay)
This is a pretty complicated bug in the delayed evaluation code. I'm afraid the following description is largely for my own benefit, it's as good a place to capture the analysis as anywhere. There seem to be three little bugs interacting; each is in a commonly used path and would probably be innocuous on its own, but together they cause the value of $source to be evaluated incorrectly. The variable $source is implemented as a MemoClosure, which means that each item of the sequence is evaluated when it is first needed. The first item is read by the <xsl:for-each select="$source"> on line 42. The evaluation of $alias needs the whole of $source, in fact the whole sequence is read in the course of evaluating the last() function, and all subsequent references should get data from the reservoir held as part of the MemoClosure. However, because $source is declared as="element()+", the sequence is piped via a CardinalityChecker. The CardinalityChecker reads the first two items in the sequence eagerly, to check that the required cardinality is satisfied. But when the sequence has only one item, it leaves the value of position set to 2. This is incorrect; the position of a SequenceIterator that has been exhausted should always be left as -1. This interacts with a bug in MemoClosure.ProgressiveIterator, whereby (on the commented-out lines 324/325) the iterator isn't detecting that some other client of the MemoClosure has read the input to completion, and does another call of next() on the input iterator. Now, a call on next() on a SequenceIterator that has been read to completion is supposed to return null, but the GroupByIterator that supports xsl:for-each-group is not doing this: if next() is called again after next() has returned null, it cycles back to the beginning of the sequence of groups. So 1. Fix MemoClosure to detect that someone else has read the sequence to completion 2. Fix CardinalityChecker to leave position set to -1 at the end 3. Fix GroupByIterator to return null if next() is called when the sequence is exhausted. Because these changes all affect common paths, some of them quite sensitive, this will need careful regression testing before I issue the patches. (And it's one of those bugs that will be very difficult to describe in the bug register!) Michael Kay
RE: Error probably related to xsl:for-each-gr - Added by Anonymous over 16 years ago
Legacy ID: #5131407 Legacy Poster: Michael Kay (mhkay)
Incidentally, again for my own records: there was another bug, which caused a crash during debugging: toString() on Value was causing premature evaluation of a Closure, which corrupted the Closure by deleting the context information needed for further evaluation. I've temporarily deleted the toString() method of Value to prevent this, but I'm not sure whether this change should be perpetuated.
RE: Error probably related to xsl:for-each-gr - Added by Anonymous over 16 years ago
Legacy ID: #5132398 Legacy Poster: Michael Kay (mhkay)
Could I have your permission please to include this stylesheet in the Saxon test suite and to submit it as part of the W3C test suite under the usual terms and conditions for W3C test material?
RE: Error probably related to xsl:for-each-gr - Added by Anonymous over 16 years ago
Legacy ID: #5132484 Legacy Poster: Vladimir Nesterovsky (vnesterovsky)
> Could I have your permission please to include > this stylesheet in the Saxon test suite and to > submit it as part of the W3C test suite under > the usual terms and conditions for W3C test material? Definitely! Please replace a top with: <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema">
RE: Error probably related to xsl:for-each-gr - Added by Anonymous over 16 years ago
Legacy ID: #5132628 Legacy Poster: Vladimir Nesterovsky (vnesterovsky)
I have minor comments: 1.In CardinalityCheckingIterator it worth to check Cardinality.allowsMany(requiredCardinality) before second = base.next(); 2. In this particular case a runtime cardinality check is not required as the cardinality can be verified during compilation.
RE: Error probably related to xsl:for-each-gr - Added by Anonymous over 16 years ago
Legacy ID: #5132645 Legacy Poster: Michael Kay (mhkay)
In theory at least, a CardinalityChecker should never be added to the expression tree (or should be removed from the expression tree) during static analysis if it can be determined statically that the required cardinality will always be satisfied.
Please register to reply