【问题标题】:XSLT merge multiple entries and add up numbersXSLT 合并多个条目并将数字相加
【发布时间】:2017-12-08 20:01:25
【问题描述】:

我有以下 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 中是两次,因此这两个将是一个条目,并且 values(2,4) 将加起来为 6。

【问题讨论】:

    标签: xml xslt


    【解决方案1】:

    这是一个非常基本的分组问题。在 XSLT 1.0 中,分组是通过使用 the Muenchian method 来完成的。

    identity transform开头...

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

    通过使用number 创建一个匹配itemxsl:key,将所有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 元素。然后使用与该键匹配的所有item 的总和创建一个新的value 元素...

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-01-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-10-13
      • 1970-01-01
      • 1970-01-01
      • 2018-07-05
      相关资源
      最近更新 更多