How do i get total cost of all the items in for-each loop?
<?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
My unfinished xsl solution:
<?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
But how to get Character name: Simmo Total cost:140
Three possibilities:
(1) Move to XSLT 2.0 and write
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.
(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):
<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>
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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With