代码之家  ›  专栏  ›  技术社区  ›  Rudramuni TP

使用XSL流在XSLT3中分组,但获取“模板规则不可流化”错误

  •  -1
  • Rudramuni TP  · 技术社区  · 6 年前

    请建议如何使用流选项xslt3进行分组。这里需要计算每个表的总高度(根据其ID分组,如果重复相同的表信息)。

    输入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:

    <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>
    

    运行时出错:

        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)
    

    要求结果:

    <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>
    

    使用Saxonee9-9-0-2j版本。请建议如何解决错误。

    2 回复  |  直到 6 年前
        1
  •  2
  •   Michael Kay    6 年前

    由于要分组的元素似乎是兄弟元素,因此不需要后代轴来查找它们,可以使用

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

    如果在实际数据中,元素不是兄弟元素,并且出现在不同的级别上,但不是递归嵌套的,那么也可以使用 innermost(//TableAndCaptionArea)

    另外:您不需要composite=“yes”,因为@id选择单个值

    高度计算可简化为:

    <xsl:attribute name="height" 
        select="sum(current-group() ! number(replace(@height, 'pt', ''))">
    
        2
  •  0
  •   Rudramuni TP    6 年前

    在…的帮助下 https://stackoverflow.com/a/44291127/3049413 (Martin Honnen先生建议),我的程序稍微修改如下[用法副本,如

    <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>