如何在for-each循环中求和这个变量?

时间:2021-07-30 13:13:45

How do i get total cost of all the items in for-each loop?

如何获得for-each循环中所有项目的总成本?

<?xml version="1.0" encoding="utf-8" ?>
<Characters>
  <Character ID="1" Name="Simmo">
    <Inventory MaxSlots="20">
      <Item ID="1" Name="Gold" Cost="1">
        <Count>100</Count>
      </Item>
      <Item ID="1" Name="hat" Cost="10">
        <Count>1</Count>
      </Item>
      <Item ID="2" Name="stick" Cost="15">
        <Count>2</Count>
      </Item>
    </Inventory>
</Character>
</Characters>

For example 1*100+10*1+15*2=140

例如1 * 100 + 10 * 1 + 15 * 2 = 140

My unfinished xsl solution:

我未完成的xsl解决方案:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" 
    exclude-result-prefixes="msxsl"
>
  <xsl:output method="html" indent="yes"/>

  <xsl:template match="/">
    <html>
      <head>
        <title>xsl file</title>
      </head>
      <body>
        <ul>
          <xsl:for-each select="/Characters/Character">
            <li>
              Character name: <xsl:value-of select="@Name"/>
              <br/>
              <xsl:for-each select="Inventory/Item">
                <xsl:variable name="cos" select="@Cost"/>
                <xsl:variable name="cou" select="Count"/>
                <xsl:variable name="kor" select="$cos*$cou"/>
                Total cost:<xsl:value-of select="$kor"/>
                <br/>
              </xsl:for-each>
              <br />
            </li>
          </xsl:for-each>
        </ul>
      </body>
    </html>
  </xsl:template>
</xsl:stylesheet>

Current output:

Character name: Simmo Total cost:100 Total cost:10 Total cost:30

字符名称:Simmo总费用:100总费用:10总费用:30

But how to get Character name: Simmo Total cost:140

但如何获得角色名称:Simmo总费用:140

2 个解决方案

#1


10  

Three possibilities:

(1) Move to XSLT 2.0 and write

(1)转到XSLT 2.0并编写

Character name:  <xsl:value-of select="@Name"/>
<br/>
Total cost:  <xsl:value-of select="
  sum(for $i in Inventory/Item return $i/@Cost * $i/Count)
"/>

(2) In XSLT 1.0, use the EXSLT node-set extension described in some detail in the related question already pointed to to (a) make a set of nodes containing the product of @Cost and Count, and (b) sum them.

(2)在XSLT 1.0中,使用已经指向的相关问题中详细描述的EXSLT节点集扩展(a)创建一组包含@Cost和Count的乘积的节点,以及(b)求和它们。

(3) Write a recursive named template to loop through the set of items, calculating a running total. That would look something like this (not tested):

(3)编写递归命名模板以遍历项集,计算运行总计。这看起来像这样(未经测试):

<xsl:template match="/">
  ... some of your code omitted here ...
  <xsl:for-each select="/Characters/Character">
    <li>
      Character name: <xsl:value-of select="@Name"/>
      <br/>
      <xsl:call-template name="sum-items">
        <xsl:with-param name="item"
          select="Inventory/Item[1]"/>
        <xsl:with-param name="accumulator"
          select="0"/>
      </xsl:call-template>
      <br />
    </li>
  </xsl:for-each>
  ...
</xsl:template>

<xsl:template name="sum-items">
  <xsl:param name="item"/>
  <xsl:param name="accumulator"/>

  <xsl:choose>
    <xsl:when test="not($item)">
      <!--* done, return result *-->
      Total cost:   <xsl:value-of select="$accumulator"/>
    </xsl:when>
    <xsl:otherwise>
      <xsl:variable name="acc" 
        select="$accumulator + ($item/@Cost * $item/Count)"/>
      <xsl:call-template name="sum-items">
        <xsl:with-param name="item"
          select="$item/following-sibling::item[1]"/>
        <xsl:with-param name="accumulator" select="$acc"/>
      </xsl:call-template>
    </xsl:otherwise>
  </xsl:when>
</xsl:template>

#2


2  

Per comment above:

以上评论:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:exsl="http://exslt.org/common"
    exclude-result-prefixes="msxsl">

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

    <xsl:template match="/">
        <html>
            <head>
                <title>xsl file</title>
            </head>
            <body>
                <ul>
                    <xsl:for-each select="/Characters/Character">
                        <li>
                            <xsl:text>Character name: </xsl:text>
                            <xsl:value-of select="@Name"/>
                            <br/>
                            <xsl:for-each select="Inventory/Item">
                                <xsl:variable name="cos" select="@Cost"/>
                                <xsl:variable name="cou" select="Count"/>
                                <xsl:variable name="kor" select="$cos*$cou"/>
                                <xsl:text>line cost:</xsl:text>
                                <xsl:value-of select="$kor"/>
                                <xsl:text> for </xsl:text>
                                <xsl:value-of select="@Name"/>
                                <br/>
                            </xsl:for-each>
                            <xsl:variable name="lines">
                                <xsl:for-each select="Inventory/Item">
                                    <cost>
                                        <xsl:value-of select="Count * @Cost"/>
                                    </cost>
                                </xsl:for-each>
                            </xsl:variable>
                            <xsl:text>Total cost:</xsl:text>
                            <xsl:value-of select="sum(exsl:node-set($lines)/cost)"/>
                            <br/>
                        </li>
                    </xsl:for-each>
                </ul>
            </body>
        </html>
    </xsl:template>
</xsl:stylesheet>

#1


10  

Three possibilities:

(1) Move to XSLT 2.0 and write

(1)转到XSLT 2.0并编写

Character name:  <xsl:value-of select="@Name"/>
<br/>
Total cost:  <xsl:value-of select="
  sum(for $i in Inventory/Item return $i/@Cost * $i/Count)
"/>

(2) In XSLT 1.0, use the EXSLT node-set extension described in some detail in the related question already pointed to to (a) make a set of nodes containing the product of @Cost and Count, and (b) sum them.

(2)在XSLT 1.0中,使用已经指向的相关问题中详细描述的EXSLT节点集扩展(a)创建一组包含@Cost和Count的乘积的节点,以及(b)求和它们。

(3) Write a recursive named template to loop through the set of items, calculating a running total. That would look something like this (not tested):

(3)编写递归命名模板以遍历项集,计算运行总计。这看起来像这样(未经测试):

<xsl:template match="/">
  ... some of your code omitted here ...
  <xsl:for-each select="/Characters/Character">
    <li>
      Character name: <xsl:value-of select="@Name"/>
      <br/>
      <xsl:call-template name="sum-items">
        <xsl:with-param name="item"
          select="Inventory/Item[1]"/>
        <xsl:with-param name="accumulator"
          select="0"/>
      </xsl:call-template>
      <br />
    </li>
  </xsl:for-each>
  ...
</xsl:template>

<xsl:template name="sum-items">
  <xsl:param name="item"/>
  <xsl:param name="accumulator"/>

  <xsl:choose>
    <xsl:when test="not($item)">
      <!--* done, return result *-->
      Total cost:   <xsl:value-of select="$accumulator"/>
    </xsl:when>
    <xsl:otherwise>
      <xsl:variable name="acc" 
        select="$accumulator + ($item/@Cost * $item/Count)"/>
      <xsl:call-template name="sum-items">
        <xsl:with-param name="item"
          select="$item/following-sibling::item[1]"/>
        <xsl:with-param name="accumulator" select="$acc"/>
      </xsl:call-template>
    </xsl:otherwise>
  </xsl:when>
</xsl:template>

#2


2  

Per comment above:

以上评论:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:exsl="http://exslt.org/common"
    exclude-result-prefixes="msxsl">

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

    <xsl:template match="/">
        <html>
            <head>
                <title>xsl file</title>
            </head>
            <body>
                <ul>
                    <xsl:for-each select="/Characters/Character">
                        <li>
                            <xsl:text>Character name: </xsl:text>
                            <xsl:value-of select="@Name"/>
                            <br/>
                            <xsl:for-each select="Inventory/Item">
                                <xsl:variable name="cos" select="@Cost"/>
                                <xsl:variable name="cou" select="Count"/>
                                <xsl:variable name="kor" select="$cos*$cou"/>
                                <xsl:text>line cost:</xsl:text>
                                <xsl:value-of select="$kor"/>
                                <xsl:text> for </xsl:text>
                                <xsl:value-of select="@Name"/>
                                <br/>
                            </xsl:for-each>
                            <xsl:variable name="lines">
                                <xsl:for-each select="Inventory/Item">
                                    <cost>
                                        <xsl:value-of select="Count * @Cost"/>
                                    </cost>
                                </xsl:for-each>
                            </xsl:variable>
                            <xsl:text>Total cost:</xsl:text>
                            <xsl:value-of select="sum(exsl:node-set($lines)/cost)"/>
                            <br/>
                        </li>
                    </xsl:for-each>
                </ul>
            </body>
        </html>
    </xsl:template>
</xsl:stylesheet>