【问题标题】:XSLT 1.0 Muenchian grouping implementation is not workingXSLT 1.0 Muenchian 分组实现不起作用
【发布时间】:2020-03-18 11:30:58
【问题描述】:

有效的 XSLT 2.0 实现:

<xsl:template name="SummaryRows">
    <xsl:for-each-group select="//Item/ItemGroup/ItemEntry" group-by="Description">
        <tr>
            <td>
                <xsl:value-of select="current-grouping-key()"/>
            </td>
            <td></td>
            <td>
                <xsl:call-template name="formatNumber2">
                    <xsl:with-param name="number" select="format-number(number(sum(current-group()/ItemSum/text())), '#.##')"/>
                </xsl:call-template>
            </td>
        </tr>
    </xsl:for-each-group>
</xsl:template>

尝试实现Muenchian grouping

<xsl:key name="items-by-description" match="ItemEntry" use="Description"/>
<xsl:template name="SummaryRows">
            <xsl:for-each select="//Item/ItemGroup/ItemEntry[count(. | key('items-by-description', Description)[1]) = 1]">
                <xsl:variable name="current-grouping-key" select="Description"/>
                <xsl:variable name="current-group" select="key('items-by-description', $current-grouping-key)"/>

                <xsl:for-each select="$current-group">
                    <tr>
                        <td>
                            <xsl:value-of select="$current-grouping-key"/>
                        </td>
                        <td/>
                        <td align="right">
                                <xsl:call-template name="formatNumber2">
                                    <xsl:with-param name="number" select="format-number(number(sum(./ItemSum/text())), '#.##')"/>
                                </xsl:call-template>
                        </td>
                    </tr>
                </xsl:for-each>
            </xsl:for-each>

</xsl:template>

xml sn-p 示例:

     <Item>
      <ItemGroup groupId="1">
        <ItemEntry>
          <Description>A</Description>
          <ItemSum>6301.1</ItemSum>
        </ItemEntry>
        <ItemEntry>
          <Description>B</Description>
          <ItemSum>901.1</ItemSum>
        </ItemEntry>
      </ItemGroup>
      <ItemGroup groupId="2">
        <ItemEntry>
          <Description>C</Description>
          <ItemSum>631.1</ItemSum>
        </ItemEntry>
        <ItemEntry>
          <Description>A</Description>
          <ItemSum>9.1</ItemSum>
        </ItemEntry>
      </ItemGroup>
    </Item>

它应该返回ItemEntryDescription 列表(假设是xslt 2.0 中的current-grouping-key())。对于每个这样的组,它必须具有该组的所有 ItemSum 的总和。

示例结果:

    A           6310.2
    B           901.1
    C           631.1

&lt;xsl:for-each select="$current-group"&gt; 循环未执行导致空集。缺少什么实现?

更新:

环境是Java 8

转换工厂属性/初始化:

System.setProperty("javax.xml.transform.TransformerFactory", "com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl");
            System.setProperty(XPathFactory.DEFAULT_PROPERTY_NAME + ":" + XPathFactory.DEFAULT_OBJECT_MODEL_URI,
                    "org.apache.xpath.jaxp.XPathFactoryImpl");

            XPathFactory xpf = XPathFactory.newInstance();

【问题讨论】:

  • 您必须展示最小但完整的 XML、XSLT 示例、您获得的输出以及您想要的输出。如果 XSLT 2 为每个组输出一个 tr 行,我不理解 XSLT 1 中的内部 xsl:for-each select="$current-group",因为这样您将为每个组中的每个项目输出一个 tr。如果我使用您拥有的变量将 XSLT 2 转录为 XSLT 1,sum(current-group()/ItemSum/text()) 将是 sum($current-group/ItemSum/text())

标签: xml xslt


【解决方案1】:

正如我在评论中所说,您不需要两个嵌套的 for-each 元素来替换单个 for-each-group,您只需使用一个,那么最小样本将是

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

    version="1.0">

  <xsl:output method="html" indent="yes" doctype-system="about:legacy-doctype"/>

<xsl:key name="items-by-description" match="ItemEntry" use="Description"/>

<xsl:template match="/*">
            <xsl:for-each select="//Item/ItemGroup/ItemEntry[count(. | key('items-by-description', Description)[1]) = 1]">
                <xsl:variable name="current-grouping-key" select="Description"/>
                <xsl:variable name="current-group" select="key('items-by-description', $current-grouping-key)"/>


                    <tr>
                        <td>
                            <xsl:value-of select="$current-grouping-key"/>
                        </td>
                        <td/>
                        <td align="right">
                                <xsl:value-of select="format-number(number(sum($current-group/ItemSum/text())), '#.##')"/>
                        </td>
                    </tr>
            </xsl:for-each>

</xsl:template>

https://xsltfiddle.liberty-development.net/3MvmXiv/3 并会为您的示例输出三个 tr 元素,就像 XSLT 2 方法 https://xsltfiddle.liberty-development.net/3MvmXiv/0

【讨论】:

  • 对于我的环境,它仅在items-by-description 键放在模板内时才有效。
  • @J.Olufsen,这听起来很奇怪,因为任何 xsl:key 声明都必须是顶级元素,即 xsl:stylesheet 的子元素。您究竟使用哪个环境需要将xsl:key 放入xsl:template 中?
  • 真正奇怪的事情是有效但 IntelliJ 抱怨语法。
猜你喜欢
  • 2018-03-28
  • 2021-11-20
  • 2015-07-30
  • 2019-12-07
  • 1970-01-01
  • 2014-02-06
  • 1970-01-01
  • 1970-01-01
  • 2014-03-19
相关资源
最近更新 更多