XSLT合并多个条目并添加数字

时间:2017-12-08 20:01:26

标签: xml xslt

ich有以下XML:

<item>
   <number>1</number>
   <value>2</value>
</item>
<item>
   <number>2</number>
   <value>22</value>
</item>
<item>
   <number>1</number>
   <value>4</value>
</item>

我想用xslt 1.0将xml转换为:

<item>
   <number>1</number>
   <value>6</value>
</item>
<item>
   <number>2</number>
   <value>22</value>
</item>

必须将相同项目编号的值相加,最后我想合并同一项目的元素。可以有n个具有相同编号的多个项目。在这个例子中,数字1的项目在xml中是两次,因此这两个将是一个条目,值(2,4)将被添加到6。

1 个答案:

答案 0 :(得分:3)

这是一个非常基本的分组问题。在XSLT 1.0中,使用the Muenchian method进行分组。

identity transform ...

开头
<xsl:template match="@*|node()">
  <xsl:copy>
    <xsl:apply-templates select="@*|node()"/>
  </xsl:copy>
</xsl:template>

使用item创建xsl:key匹配number,按item对所有number进行分组...

<xsl:key name="items" match="item" use="number"/>

从所有item的父级的上下文(以doc为例)输出元素的副本并将模板应用于第一个item在组(和任何属性)......

<xsl:template match="doc">
  <xsl:copy>
    <xsl:apply-templates select="@*|item[count(.|key('items',number)[1])=1]"/>
  </xsl:copy>
</xsl:template>

添加与item匹配的模板并输出其副本。将模板应用于任何属性和number元素。然后创建一个新的value元素,其中所有item的总和与该键匹配...

<xsl:template match="item">
  <xsl:copy>
    <xsl:apply-templates select="@*|number"/>
    <value><xsl:value-of select="sum(key('items',number)/value)"/></value>
  </xsl:copy>
</xsl:template>

完整示例......

XML输入(添加了一个根元素doc以使输入格式正确)

<doc>
    <item>
        <number>1</number>
        <value>2</value>
    </item>
    <item>
        <number>2</number>
        <value>22</value>
    </item>
    <item>
        <number>1</number>
        <value>4</value>
    </item>
</doc>

XSLT 1.0

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:key name="items" match="item" use="number"/>

  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="doc">
    <xsl:copy>
      <xsl:apply-templates select="@*|item[count(.|key('items',number)[1])=1]"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="item">
    <xsl:copy>
      <xsl:apply-templates select="@*|number"/>
      <value><xsl:value-of select="sum(key('items',number)/value)"/></value>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

XML输出

<doc>
   <item>
      <number>1</number>
      <value>6</value>
   </item>
   <item>
      <number>2</number>
      <value>22</value>
   </item>
</doc>