在XSLT中执行SUM操作

时间:2013-05-19 16:20:58

标签: xslt

在下面的输入中,我们必须检查供应商代码是否与任何节点供应商代码匹配,然后我们必须对Quantity.otherwise执行总和操作直接映射数量。

输入:

<Move-Afile>
  <Afile>
    <Item>
    <suppliercode>1</suppliercode>
      <PackNumber>1234</PackNumber>
      <Quantity>12</Quantity>
    </Item>
    <Item>
    <suppliercode>2</suppliercode>
      <PackNumber>567</PackNumber>
      <Quantity>3</Quantity>
    </Item>
    <Item>
    <suppliercode>1</suppliercode>
      <PackNumber>567</PackNumber>
      <Quantity>8</Quantity>
    </Item>
    <Item>
    <suppliercode>3</suppliercode>
      <PackNumber>126</PackNumber>
      <Quantity>11</Quantity>
    </Item>
    <Item>
    <suppliercode>4</suppliercode>
      <PackNumber>876</PackNumber>
      <Quantity>32</Quantity>
    </Item>
  </Afile>
</Move-Afile>

如果供应商代码相等,则对数量执行总和操作,否则直接映射数量。

输出:

<A>
  <target>
    <Item>
    <suppliercode>1</suppliercode>
      <PackNumber>1234</PackNumber>
      <Quantity>20</Quantity>
    </Item>
    <Item>
    <suppliercode>2</suppliercode>
      <PackNumber>567</PackNumber>
      <Quantity>3</Quantity>
    </Item>
    <Item>
    <suppliercode>1</suppliercode>
      <PackNumber>567</PackNumber>
      <Quantity>20</Quantity>
    </Item>
    <Item>
    <suppliercode>3</suppliercode>
      <PackNumber>126</PackNumber>
      <Quantity>11</Quantity>
    </Item>
    <Item>
    <suppliercode>4</suppliercode>
      <PackNumber>876</PackNumber>
      <Quantity>32</Quantity>
    </Item>
  </target>
</A>

我需要在一个单独的临时变量中使用sum逻辑,如下所示。

<varaible name=tempvar>
<xsl:choose>
<xsl:when suppliercode=suppliercode>

<xsl:value-of select=sum(quntity)/>

<xsl:when>

<xsl:otherwise>

<xsl:value-of select=quntity/>

</xsl:otherwise>

</xsl:choose>

</variable>

2 个答案:

答案 0 :(得分:0)

此样式表可满足您的需求。它会向下复制Item的所有元素,并有一个特殊模板,可以通过添加Quantity元素中具有相同元素的所有Quantity元素的值来更改Item的值价值suppliercode

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:strip-space elements="*"/>
  <xsl:output method="xml" indent="yes" encoding="UTF-8" omit-xml-declaration="yes"/>

  <xsl:template match="/">
    <A>
      <target>
        <xsl:apply-templates select="Move-Afile/Afile/Item"/>
      </target>
    </A>
  </xsl:template>

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

  <xsl:template match="Quantity">
    <xsl:variable name="supplier-code" select="parent::Item/suppliercode"/>
    <xsl:copy>
      <xsl:value-of select="sum(ancestor::Afile/Item[suppliercode = $supplier-code]/Quantity)"/>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

<强>输出

<A>
   <target>
      <Item>
         <suppliercode>1</suppliercode>
         <PackNumber>1234</PackNumber>
         <Quantity>20</Quantity>
      </Item>
      <Item>
         <suppliercode>2</suppliercode>
         <PackNumber>567</PackNumber>
         <Quantity>3</Quantity>
      </Item>
      <Item>
         <suppliercode>1</suppliercode>
         <PackNumber>567</PackNumber>
         <Quantity>20</Quantity>
      </Item>
      <Item>
         <suppliercode>3</suppliercode>
         <PackNumber>126</PackNumber>
         <Quantity>11</Quantity>
      </Item>
      <Item>
         <suppliercode>4</suppliercode>
         <PackNumber>876</PackNumber>
         <Quantity>32</Quantity>
      </Item>
   </target>
</A>

<强>更新 要在使用之前将总数放入变量,您可以使用此

替换最后一个模板
  <xsl:template match="Quantity">
    <xsl:variable name="supplier-code" select="parent::Item/suppliercode"/>
    <xsl:variable name="total" select="sum(ancestor::Afile/Item[suppliercode = $supplier-code]/Quantity)"/>
    <xsl:copy>
      <xsl:value-of select="$total"/>
    </xsl:copy>
  </xsl:template>

$total的值设置为具有相同供应商代码的数量之和。

答案 1 :(得分:0)

这种简短而有效(使用密钥)转换:

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

 <xsl:key name="kQuantityBySupplier" match="Quantity" use="../suppliercode"/>

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

 <xsl:template match="/*">
  <A>
    <target>
      <xsl:apply-templates select="*/node()"/>
    </target>
  </A>
 </xsl:template>

 <xsl:template match="Quantity/text()">
  <xsl:value-of select="sum(key('kQuantityBySupplier', ../../suppliercode))"/>
 </xsl:template>
</xsl:stylesheet>

应用于提供的XML文档时:

<Move-Afile>
  <Afile>
    <Item>
    <suppliercode>1</suppliercode>
      <PackNumber>1234</PackNumber>
      <Quantity>12</Quantity>
    </Item>
    <Item>
    <suppliercode>2</suppliercode>
      <PackNumber>567</PackNumber>
      <Quantity>3</Quantity>
    </Item>
    <Item>
    <suppliercode>1</suppliercode>
      <PackNumber>567</PackNumber>
      <Quantity>8</Quantity>
    </Item>
    <Item>
    <suppliercode>3</suppliercode>
      <PackNumber>126</PackNumber>
      <Quantity>11</Quantity>
    </Item>
    <Item>
    <suppliercode>4</suppliercode>
      <PackNumber>876</PackNumber>
      <Quantity>32</Quantity>
    </Item>
  </Afile>
</Move-Afile>

生成想要的正确结果

<A>
   <target>
      <Item>
         <suppliercode>1</suppliercode>
         <PackNumber>1234</PackNumber>
         <Quantity>20</Quantity>
      </Item>
      <Item>
         <suppliercode>2</suppliercode>
         <PackNumber>567</PackNumber>
         <Quantity>3</Quantity>
      </Item>
      <Item>
         <suppliercode>1</suppliercode>
         <PackNumber>567</PackNumber>
         <Quantity>20</Quantity>
      </Item>
      <Item>
         <suppliercode>3</suppliercode>
         <PackNumber>126</PackNumber>
         <Quantity>11</Quantity>
      </Item>
      <Item>
         <suppliercode>4</suppliercode>
         <PackNumber>876</PackNumber>
         <Quantity>32</Quantity>
      </Item>
   </target>
</A>

请注意

该变换的时间复杂度是线性的(O(N))。这比重复扫描所有元素以找到具有给定suppliercode的元素(具有二次(O(N ^ 2))时间复杂度的元素的效率要高几个数量级。


<强>更新

OP已指定一项新要求,即在变量中捕获总和或单一数量:

只需修改

 <xsl:template match="Quantity/text()">
  <xsl:value-of select="sum(key('kQuantityBySupplier', ../../suppliercode))"/>
 </xsl:template>

进入

 <xsl:template match="Quantity/text()">
  <xsl:variable name="vSum" select="sum(key('kQuantityBySupplier', ../../suppliercode))"/>
  <xsl:value-of select="$vSum"/>
 </xsl:template>