xsl:在 for-each-group() 中排序

Posted

技术标签:

【中文标题】xsl:在 for-each-group() 中排序【英文标题】:xsl:sort inside for-each-group() 【发布时间】:2016-04-09 23:38:30 【问题描述】:

由于某种原因,自升级到 Saxon 9.7.0.1 后,for-each-group 中的 xsl:sort 引发异常

XML-

<table class="vv">
        <tr><td>woot1</td><td>woot2</td></tr>
        <tr><td>woot1</td><td>woot2</td></tr>
        <tr><td>woot1</td><td>woot2</td></tr>
        <tr><td>woot1</td><td>woot2</td></tr>
</table>

XSL-

<xsl:template match="/">
  <xsl:apply-templates/>
</xsl:template>

<xsl:template match="table[@class='vv']">
    <div class="row">
        <xsl:for-each-group select="tr" group-by="td[1]/text()">
            <xsl:sort/>
            test
        </xsl:for-each-group>
    </div>
</xsl:template>

错误-

只是想验证这是否是 Saxon 中的错误,或者在 XSLT 3.0 中过去的工作方式发生了变化

【问题讨论】:

我可以用 9.7 EE 重现问题,但不能用 PE 或 HE。你也在用 EE 吗? 【参考方案1】:

IncompatibleClassChangeError 通常意味着 JVM 在运行时加载了一个类,这与它在编译时的方式不同。也就是说,代码是使用类路径编译的,其中包含与运行时加载的版本不同的某个库类的版本。

两种可能的研究理论:

(a) 在这种情况下,从表面上看,所涉及的所有类似乎都是 Saxon 类,因此这可能表明您在类路径上有多个 Saxon 版本,并且由于某种原因代码正在从两者加载。

(b) 另一方面,我可以在您的屏幕截图的底部看到一半被裁剪的行,这表明您正在使用启用了字节码生成的 Saxon-EE,这可能表明存在错误在字节码生成中。尝试禁用字节码生成以查看问题是否消失。例如通过调用Processor.setConfigurationProperty(FeatureKeys.GENERATE_BYTECODE, false)

如果确实是字节码生成错误,请将其记录在http://saxonica.plan.io,以便我们可以正确跟踪。我们几乎可以肯定需要访问一个样式表来演示这个问题。

【讨论】:

感谢您的回复。刚刚验证项目中只使用了一个 Saxon jar。我们正在检查是否启用了字节码生成。 原来我们启用了字节码生成。如果我们禁用它,它就会消失。这是问题-saxonica.plan.io/issues/2573【参考方案2】:

我不认为这是一个真正的修复,但是,奇怪的是,您可以在 for-each-group 正文中添加 &lt;xsl:value-of select="current-grouping-key()"/&gt; 语句,异常就会消失。可以在评论中。

<xsl:template match="table[@class='vv']" mode="copy">
    <div class="row">
        <xsl:for-each-group select="tr" group-by="td[1]/text()">
            <xsl:sort/>
            <xsl:comment><xsl:value-of select="current-grouping-key()"/></xsl:comment>
           test 
        </xsl:for-each-group>
    </div>
</xsl:template>

【讨论】:

其实一点也不神秘。对样式表的微小更改可能会使优化器走上完全不同的道路,从而导致执行计划大不相同。这就是为什么我们通常需要一个实际演示问题的重现,而不仅仅是一个代码 sn-p。 (感谢提供一个)。 虽然这种情况的原因很有趣,并且在 Saxon 错误条目中进行了讨论。

以上是关于xsl:在 for-each-group() 中排序的主要内容,如果未能解决你的问题,请参考以下文章

父组的 XSLT 分组键

如何使用 XSL 中的每个组

来自变量的 XSLT for-each-group 不起作用

如何使用 Apache Camel 在 XSLT 中为每个组申请

XSLT使用for-each-group进行分组并使用填充元素

最近的聊天应该在 quickblox 历史列表中排在第一位