-1

Please suggest how to do grouping withstream option xslt3. Here total height of each Table (grouping on its ID, if same table info repeated) needs calculate.

Input XML:

<AreaRoot>
<TableAndCaptionArea generated-by="table" id="t0005-tSC"  height="90.488pt" display-role="block">
<a>One</a>
</TableAndCaptionArea>
<TableAndCaptionArea generated-by="table" id="t0005-tSC" height="33.3pt" display-role="block">
<a>Two</a>
</TableAndCaptionArea>
<TableAndCaptionArea generated-by="table" id="t0005-tDC" height="91.594pt" display-role="block">
<a>Three</a>
</TableAndCaptionArea>
<TableAndCaptionArea generated-by="table" id="t0005-tLS" height="91.594pt" display-role="block">
<a>Four</a>
</TableAndCaptionArea>
</AreaRoot>

XSLT 3.0:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0">

<!--xsl:mode streamable="yes"/-->
<xsl:mode streamable="yes" on-no-match="shallow-copy"/>

<xsl:output method="text"/>

<xsl:template match="/">
    <xsl:fork>
        <xsl:for-each-group select="descendant::*:TableAndCaptionArea[@id]" composite="yes" group-by="@id">
            <table>
                <xsl:attribute name="id"><xsl:value-of select="@id"/></xsl:attribute>
                <!--Height of a table -->
                <xsl:attribute name="height">
                    <xsl:variable name="var1">
                        <a>
                            <xsl:for-each select="current-group()/@height">
                                <b><xsl:value-of select="replace(., 'pt', '')"/></b>
                            </xsl:for-each>
                        </a>
                    </xsl:variable>
                    <xsl:value-of select="sum($var1/*:a/*:b)"/>
                </xsl:attribute>
            </table>
        </xsl:for-each-group>
    </xsl:fork>
</xsl:template>

</xsl:stylesheet>

Getting Error while running:

    Error on line 8 of Stream2.xsl:
XTSE3430: Template rule is not streamable
* The xsl:for-each-group/@select expression has crawling posture (that is, itcan select   overlapping nodes)

Required Result:

<ATRinfo>
    <height>
    <table id="t0005-tSC" height="123.788"/>
    <table id="t0005-tDC" height="91.594" />
    <table id="t0005-tLS" height="91.594"/>
    </height>
</ATRinfo>

Using SaxonEE9-9-0-2J version. Please suggest how to resolve the error.

Rudramuni TP
  • 1,268
  • 2
  • 16
  • 26
  • https://stackoverflow.com/a/44291127/6805256 You wrote a comment in mid '17. Are there any differences compared to this question? – uL1 Jan 11 '19 at 12:26

2 Answers2

2

Since the elements to be grouped appear to be siblings, you don't need the descendant axis to find them, you can use

<xsl:for-each-group select="/*/TableAndCaptionArea" 

If in your actual data the elements are not siblings, and occur on different levels, but are not nested recursively, then you could also use innermost(//TableAndCaptionArea)

Also: You don't need composite="yes" because @id selects a single value

and: The computation of height can be simplified to:

<xsl:attribute name="height" 
    select="sum(current-group() ! number(replace(@height, 'pt', ''))">
Michael Kay
  • 156,231
  • 11
  • 92
  • 164
  • Sir, thanks for the suggestion, but getting ' XTSE3430: Template rule is not streamable' error, while converting. – Rudramuni TP Jan 14 '19 at 07:43
  • Decsendant axis required, because those may come in any level nesting, thats why I called in Decsendant. – Rudramuni TP Jan 14 '19 at 07:49
  • If you're still hitting problems then please either extend your question or write a new question. It's not possible to explain streamability errors without precise details of your source code, and it's also necessary to have an understanding of the source document structure in order to suggest how to make your code streamable. – Michael Kay Jan 15 '19 at 19:00
  • In Saxon9HE we are unable to get the result for same input which is around some 200 MB, but small inputs, able to get the result, thats why XSLT3 stream help thought of taking. But same grouping concept working in XSLT2. Please suggest for the XSLT3 with descendant and group code. – Rudramuni TP Jan 16 '19 at 05:49
  • Did you read my comment? I'm having trouble finding a different way to explain that we can't help you without the information that I asked for. – Michael Kay Jan 16 '19 at 10:47
  • Thanks for the suggestions sir. – Rudramuni TP Jan 16 '19 at 13:51
0

With the help of https://stackoverflow.com/a/44291127/3049413 (Martin Honnen Sir suggestion), my program slightly modified as below [ copy-of usage like

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0">
<xsl:mode streamable="yes" on-no-match="shallow-copy"/>

<xsl:template match="/">
    <xsl:element name="ATRinfo">
    <xsl:fork>
        <xsl:for-each-group select="copy-of(descendant::*:TableAndCaptionArea[@id])" 
                        group-by="@id">
            <table>
                <xsl:attribute name="id"><xsl:value-of select="@id"/></xsl:attribute>
                <!--Height of a table -->
                <xsl:attribute name="height">
                    <xsl:variable name="var1">
                        <a>
                            <xsl:for-each select="current-group()/@height">
                                <b><xsl:value-of select="replace(., 'pt', '')"/></b>
                            </xsl:for-each>
                        </a>
                    </xsl:variable>
                    <xsl:value-of select="sum($var1/*:a/*:b)"/>
                </xsl:attribute>
            </table>
        </xsl:for-each-group>
    </xsl:fork>
    </xsl:element>
</xsl:template>

</xsl:stylesheet>
Rudramuni TP
  • 1,268
  • 2
  • 16
  • 26
  • As Michael had already pointed out, you have a single item grouping key with `@id` so for sure you don't need any `composite="yes"` on the `for-each-group`. And also following Michael's suggestion, (with the correction to use `outermost` instead of `innermost`), I think it should suffice to use `` to select any `TableAndCaptionArea` elements at any level in a streamble way as long as they are not nested. – Martin Honnen Jan 20 '19 at 12:55
  • Using `copy-of` is always a last resort and is suggested in the linked answer as one way to make sure the grouping key can access child elements, as your grouping key selects an attribute you don't need `copy-of` to solve that part of the problem. – Martin Honnen Jan 20 '19 at 12:57