在XSLT中对节点集进行分组

时间:2014-04-11 11:02:59

标签: xslt xslt-1.0 grouping

我知道用于XSLT的Muenchian分组方法,但我看到的所有实现都依赖于单个节点作为分组的值。在这种情况下,我想分组一个节点集。在下面的输入中,我想分组输出/输出部分参考。

我尝试构建

等键
<xsl:key name="refsKey" match="/processes/process" use="outputs/output_part_ref"/>

当然outputs / output_part_ref与第一个节点匹配,与节点集不匹配。

输入

<?xml version="1.0" encoding="UTF-8"?>
<processes>
    <process>
        <name>ProcessA</name>
        <input_qty>1200</input_qty>
        <outputs>
            <output_part_ref>1</output_part_ref>
            <output_part_ref>2</output_part_ref>
            <output_part_ref>3</output_part_ref>
        </outputs>
    </process>
    <process>
        <name>ProcessB</name>
        <input_qty>1300</input_qty>
        <outputs>
            <output_part_ref>1</output_part_ref>
            <output_part_ref>2</output_part_ref>
            <output_part_ref>3</output_part_ref>
        </outputs>
    </process>
    <process>
        <name>ProcessC</name>
        <input_qty>770</input_qty>
        <outputs>
            <output_part_ref>1</output_part_ref>
            <output_part_ref>2</output_part_ref>
        </outputs>
    </process>
</processes>

示例输出

<html>
...
<table>
    <tr>
        <td>2500</td>
        <td>1</td>
        <td>2</td>
        <td>3</td>
    </tr>
    <tr>
        <td>770</td>
        <td>1</td>
        <td>2</td>
    </tr>
</table>
...
</html>

1 个答案:

答案 0 :(得分:2)

如果构成密钥的元素数量不固定,那么我同意迈克尔,我们需要先计算密钥并在XSLT 1.0中使用exsl:node-set或类似的代码:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:exsl="http://exslt.org/common" exclude-result-prefixes="exsl">

<xsl:output method="html" indent="yes"/>

<xsl:key name="refsKey" match="process" use="key"/>

<xsl:variable name="rtf1">
  <xsl:apply-templates select="processes/process" mode="key"/>
</xsl:variable>

<xsl:template match="process" mode="key">
  <xsl:copy>
    <key>
      <xsl:for-each select="outputs/output_part_ref">
        <xsl:sort select="." data-type="number"/>
        <xsl:if test="position() > 1">|</xsl:if>
        <xsl:value-of select="."/>
      </xsl:for-each>
    </key>
    <xsl:copy-of select="node()"/>
  </xsl:copy>
</xsl:template>

<xsl:variable name="ns1" select="exsl:node-set($rtf1)/process"/>

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

<xsl:template match="processes">
  <table>
    <xsl:apply-templates select="$ns1[generate-id() = generate-id(key('refsKey', key)[1])]"/>
  </table>
</xsl:template>

<xsl:template match="process">
  <tr>
    <td><xsl:value-of select="sum(key('refsKey', key)/input_qty)"/></td>
    <xsl:for-each select="outputs/output_part_ref">
      <td>
        <xsl:value-of select="."/>
      </td>
    </xsl:for-each>
  </tr>
</xsl:template>

</xsl:stylesheet>