Reputation: 8020
How can i add values based on another value?
<?xml version="1.0" encoding="UTF-8"?>
<items>
<item id="A1" quantity="5">
<info type="ram x1" import="CA" />
</item>
<item id="A2" quantity="3">
<info type="ram x1" import="SA" />
</item>
<item id="A3" quantity="10">
<info type="ram x2" import="AU" />
</item>
</items>
I need to add all quantities based on the type
for example i need an output as,
ram x1 quantity=8 ram x2 quantity=10
<?xml version="1.0" encoding="UTF-8"?>
<items>
<details type="ram x1" quantity="8"/>
<details type="ram x2" quantity="10"/>
</items>
tried for-each-group to get quantity first to see if it works,
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="html" indent="yes" />
<xsl:template match="items">
<xsl:for-each-group select="item" group-by="info/@type">
<xsl:value-of select="sum(@quantity)" />
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>
Upvotes: 2
Views: 660
Reputation: 22617
@Kirill Polishchuck has given a good answer already, I would like to add a full stylesheet to illustrate this.
It outputs XML formatted in the way you have shown it should be. Apart from making use of current-group()
, there is also an interesting application of current-grouping-key()
which retrieves the value that caused the current items to be grouped together.
You have specified xsl:output method
to be HTML, but your expected output looks like XML. Therefore, I have altered it to output XML.
Stylesheet
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="xml" indent="yes" />
<xsl:template match="items">
<xsl:copy>
<xsl:for-each-group select="item" group-by="info/@type">
<details>
<xsl:attribute name="type">
<xsl:value-of select="current-grouping-key()"/>
</xsl:attribute>
<xsl:attribute name="quantity">
<xsl:value-of select="sum(current-group()/@quantity)" />
</xsl:attribute>
</details>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Output
<?xml version="1.0" encoding="UTF-8"?>
<items>
<details type="ram x1" quantity="8"/>
<details type="ram x2" quantity="10"/>
</items>
An even more concise (but more intricate) version uses so-called attribute value templates:
<xsl:for-each-group select="item" group-by="info/@type">
<details type="{current-grouping-key()}" quantity="{sum(current-group()/@quantity)}"/>
</xsl:for-each-group>
Upvotes: 0
Reputation: 56162
Use current-group()
function, i.e.:
<xsl:value-of select="sum(current-group()/@quantity)" />
Upvotes: 3