Re: Saxon 9.5 Not Emitting Expected Messages Within xsl:iterate
Eliot Kimber <ekimber-xb9TSTQ6enFWk0Htik3J/[email protected]> Fri, 16 Oct 2020 12:10:24 -0500
| Newsgroups | gmane.text.xml.saxon.help |
|---|---|
| Message-ID | <[email protected]> |
Update: I rewrote the xsl:iterate as a recursive function and I'm still seeing missing messages, so probably the use of xsl:iterate is not involved and it's either my coding error or some other issue with Saxon 9.5. Cheers, E. -- Eliot Kimber http://contrext.com On 10/16/20, 11:03 AM, "Eliot Kimber" <[email protected]> wrote: For my day job I'm stuck on Saxon 9.5. I've read the 9.5 documentation and I think I have correctly understood the 9.5 support for xsl:iterate and maps but I'm getting unexpected behavior so I wanted to make sure I'm not trying to do the impossible. I know it's hard (and painful) to support a version this old, but I have to ask. The data processing problem I'm trying to solve is working out the correct column positions of CALS table cells in the face of row spans. I'm solving this by iterating over the <entry> elements in the input thead or tbody and constructing map entries where the key is the row/column position of all the unit cells, which means that for any given cell, there will be map entries for any preceding unit cells covered by preceding horizontal or vertical row spans, allowing me to then calculate the effective starting column for any given <entry> element. This is an ideal candidate for xsl:iterate. What I'm seeing is that my code is not giving me the correct answer (basically, the bit that should be constructing row-span-reflecting map entries is not doing so). I'm working in Oxygen but I've got Saxon 9.5 set up as an external transform engine so I can run it rather than the newest version. This means I can't use Oxygen's debugger and must rely on messages. What I'm seeing is that messages that should not be conditional or deferred by late variable binding are not being emitted at all. I think my question is: should I expect xsl:iterate and maps to work reliably in Saxon 9.5 and if the answer is yes, what could cause messages to not be emitted? I don't think I have any coding errors--the transform runs and for the case where there are no spans in a row it gives the correct answer. It does not give the correct answer for spans because the necessary map entries are not being created, suggesting that the iterations are short circuiting, which I'm trying to verify using debugging messages. In the function given below, what I see, for example, is that for this block of code: <xsl:variable name="childpos" as="xs:integer" select="count(($cell, preceding-sibling::*[contains(@class, ' topic/entry ')]))"/> <xsl:message>+ [DEBUG] local:calculateColumnPositions(): childpos="<xsl:value-of select="$childpos"/>"</xsl:message> <xsl:variable name="rownum" as="xs:integer" select="count(($cell/parent::*, $cell/parent::*/preceding-sibling::*[contains(@class, ' topic/row ')]))"/> <xsl:message>+ [DEBUG] local:calculateColumnPositions(): rownum="<xsl:value-of select="$rownum"/>"</xsl:message> The first message (childpos=...) is emitted but the next one (rownum=...) is not, even though both are just doing xpaths and not using some other function. Because this is inside xsl:iterate I suspect there's some early-implementation issue going on. Should I not be trying to use xsl:iteration in Saxon 9.5 and go back to recursive functions? Thanks, Eliot Here's the function I'm running: <xsl:function name="local:calculateColumnPositions" as="map(*)"> <xsl:param name="context" as="element()"/> <xsl:param name="colspecs" as="element()*"/> <xsl:message>+ [DEBUG] *** local:calculateColumnPositions(): Starting. Colspecs: <xsl:sequence select="$colspecs"/></xsl:message> <!-- Construct a set of map entries where the key is the x/y position of a given unit cell in the table and the value is the entry that occupies that cell. Use xsl:iterate to examine every entry in a set of rows (thead or tbody) --> <xsl:variable name="result" as="map(*)"> <xsl:message>+ [DEBUG] Iteration to construct entry map:</xsl:message> <xsl:iterate select="$context//*[contains(@class, ' topic/entry ')]"> <xsl:param name="matrix-map" as="map(*)" select="map{}"/> <xsl:on-completion> <xsl:sequence select="$matrix-map"/> </xsl:on-completion> <xsl:variable name="cell" as="element()" select="."/> <xsl:message>+ [DEBUG] local:calculateColumnPositions(): [Iteration <xsl:value-of select="position()"/>] <xsl:value-of select="$cell"/>:</xsl:message> <xsl:variable name="childpos" as="xs:integer" select="count(($cell, preceding-sibling::*[contains(@class, ' topic/entry ')]))"/> <xsl:message>+ [DEBUG] local:calculateColumnPositions(): childpos="<xsl:value-of select="$childpos"/>"</xsl:message> <xsl:variable name="rownum" as="xs:integer" select="count(($cell/parent::*, $cell/parent::*/preceding-sibling::*[contains(@class, ' topic/row ')]))"/> <xsl:message>+ [DEBUG] local:calculateColumnPositions(): rownum="<xsl:value-of select="$rownum"/>"</xsl:message> <!-- Number of rows including current row that this cell spans (minimum is 1): --> <xsl:variable name="rows-spanned" as="xs:integer" select=" if (exists(@morerows)) then xs:integer(@morerows) + 1 else 1 " /> <xsl:message>+ [DEBUG] local:calculateColumnPositions(): rows-spanned="<xsl:value-of select="$rows-spanned"/>"</xsl:message> <xsl:variable name="starting-column" as="xs:integer" select="local:getEffectiveColumnPosition($matrix-map, $rownum, $childpos)" /> <xsl:message>+ [DEBUG] local:calculateColumnPositions(): starting-column="<xsl:value-of select="$starting-column"/>"</xsl:message> <!-- Number of columns spanned, including the starting column (minimum is 1) --> <xsl:variable name="cols-spanned" as="xs:integer" select="local:getColSpanForCell($cell, $colspecs)" /> <xsl:message>+ [DEBUG] local:calculateColumnPositions(): cols-spanned="<xsl:value-of select="$cols-spanned"/>"</xsl:message> <xsl:message>+ [DEBUG] local:calculateColumnPositions(): Calculating cell entries for cell "<xsl:value-of select="$cell"/>"</xsl:message> <xsl:variable name="ending-row" as="xs:integer" select="$rownum + ($rows-spanned - 1)"/> <xsl:message>+ [DEBUG] local:calculateColumnPositions(): rownum: <xsl:value-of select="$rownum"/>, ending-row: <xsl:value-of select="$ending-row"/></xsl:message> <xsl:variable name="ending-column" as="xs:integer" select="$starting-column + ($cols-spanned - 1)"/> <xsl:message>+ [DEBUG] local:calculateColumnPositions(): starting-column: <xsl:value-of select="$starting-column"/>, ending-column: <xsl:value-of select="$ending-column"/></xsl:message> <xsl:for-each select="$rownum to $ending-row"> <xsl:variable name="row" as="xs:integer" select="."/> <xsl:message>+ [DEBUG] local:calculateColumnPositions(): row: <xsl:value-of select="$row"/> </xsl:message> <xsl:for-each select="$starting-column to $ending-column"> <xsl:variable name="col" as="xs:integer" select="."/> <xsl:message>+ [DEBUG] local:calculateColumnPositions(): col: <xsl:value-of select="$col"/></xsl:message> <xsl:variable name="key" as="xs:string" select="$row || ',' || $col"/> <xsl:message>+ [DEBUG] local:calculateColumnPositions(): Creating map entry {<xsl:value-of select="$key"/>: <xsl:value-of select="$cell"/>}</xsl:message> </xsl:for-each> </xsl:for-each> <xsl:variable name="cells-entries" as="map(*)*"> <xsl:for-each select="$rownum to $ending-row"> <xsl:variable name="row" as="xs:integer" select="."/> <xsl:message>+ [DEBUG] local:calculateColumnPositions(): row: <xsl:value-of select="$row"/> </xsl:message> <xsl:for-each select="$starting-column to $ending-column"> <xsl:variable name="col" as="xs:integer" select="."/> <xsl:message>+ [DEBUG] local:calculateColumnPositions(): col: <xsl:value-of select="$col"/></xsl:message> <xsl:variable name="key" as="xs:string" select="$row || ',' || $col"/> <xsl:sequence select="map:entry($key, $cell)"></xsl:sequence> </xsl:for-each> </xsl:for-each> </xsl:variable> <!-- <xsl:variable name="cells-entries" as="map(*)*" select=" for $p in $starting-column to ($starting-column + ($cols-spanned - 1)) return for $q in $rownum to ($rownum + ($rows-spanned - 1)) return map:entry($q || ',' || $p, $cell) " />--> <xsl:message>+ [DEBUG] local:calculateColumnPositions(): cells-entries:</xsl:message> <xsl:for-each select="$cells-entries"> <xsl:variable name="key" as="xs:string" select="map:keys(.)"/> <xsl:message>+ [DEBUG] local:calculateColumnPositions(): [Cell <xsl:value-of select="$key"/>] <xsl:value-of select="map:get(., $key)"/></xsl:message> </xsl:for-each> <xsl:next-iteration> <xsl:with-param name="matrix-map" select="map:new(($matrix-map, $cells-entries))"/> </xsl:next-iteration> </xsl:iterate> </xsl:variable> <xsl:message>+ [DEBUG] Result map:</xsl:message> <xsl:for-each select="map:keys($result)"> <xsl:sort select="."/> <xsl:variable name="key" as="xs:string" select="."/> <xsl:variable name="cell" as="element()" select="map:get($result, $key)"/> <xsl:message>[<xsl:value-of select="$key"/>] [entry <xsl:value-of select="for $att in ($cell/@morerows, $cell/@namest, $cell/@nameend) return (' ' || name($att) || '=' || string($att))"/>]<xsl:value-of select="map:get($result, $key)"/></xsl:message> </xsl:for-each> <xsl:sequence select="$result"/> </xsl:function> -- Eliot Kimber http://contrext.com _______________________________________________ saxon-help mailing list archived at http://saxon.markmail.org/ [email protected] https://lists.sourceforge.net/lists/listinfo/saxon-help _______________________________________________ saxon-help mailing list archived at http://saxon.markmail.org/ [email protected] https://lists.sourceforge.net/lists/listinfo/saxon-help