I'm currently working on a tricky transformation in which I need to sum the amount of the game articles price value when the article appears twice and to exclude the second article from the output.
Explanation : Each article has a id, name, price and a copy number. In my case, I always have two copies. Copy 0 & Copy 1. If an article has two copies, then we add the price of article copy 1 in article copy 0 and we exclude copy 1 from the output
I'm not exactly sure on how to approach this requirement.
The XML input
<?xml version="1.0" encoding="UTF-8"?>
<wd:Report_Data>
<wd:Report_Entry>
<wd:id>1000</wd:id>
<wd:name>Call of Duty</wd:name>
<wd:price>50.12</wd:price>
<wd:copy>0</wd:copy>
</wd:Report_Entry>
<wd:Report_Entry>
<wd:id>1000</wd:id>
<wd:name>Call of Duty</wd:name>
<wd:price>60.0</wd:price>
<wd:copy>1</wd:copy>
</wd:Report_Entry>
<wd:Report_Entry>
<wd:id>2000</wd:id>
<wd:name>Metal Slug</wd:name>
<wd:price>75.00</wd:price>
<wd:copy>0</wd:copy>
</wd:Report_Entry>
<wd:Report_Entry>
<wd:id>3000</wd:id>
<wd:name>Need For Speed</wd:name>
<wd:price>40.00</wd:price>
<wd:copy>0</wd:copy>
</wd:Report_Entry>
</wd:Report_Data>
The expected XML output:
<?xml version="1.0" encoding="UTF-8"?>
<wd:Report_Data>
<wd:Report_Entry>
<wd:id>1000</wd:id>
<wd:name>Call of Duty</wd:name>
<wd:price>110.12</wd:price>
<wd:copy>0</wd:copy>
</wd:Report_Entry>
<wd:Report_Entry>
<wd:id>2000</wd:id>
<wd:name>Metal Slug</wd:name>
<wd:price>75.00</wd:price>
<wd:copy>0</wd:copy>
</wd:Report_Entry>
<wd:Report_Entry>
<wd:id>3000</wd:id>
<wd:name>Need For Speed</wd:name>
<wd:price>40.00</wd:price>
<wd:copy>0</wd:copy>
</wd:Report_Entry>
</wd:Report_Data>
Following @michael.hor257k recommendation, I was able to create a grouping structure and sum the price. However, I still don't get the expected result
XSLT
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:wd="http://www.workday.org/" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:template match="/">
<xsl:for-each-group select="wd:Report_Data/wd:Report_Entry" group-by="wd:id">
<xsl:copy>
<xsl:copy-of select="wd:id"/>
<xsl:copy-of select="wd:name"/>
<wd:price>
<xsl:value-of select="sum(current-group()/wd:price)" />
</wd:price>
<xsl:copy-of select="wd:copy"/>
</xsl:copy>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>
Result (not what I want )
<wd:Report_Entry xmlns:wd="http://www.workday.org/">
<wd:id>1000</wd:id>
<wd:name>Call of Duty</wd:name>
<wd:price xmlns:xs="http://www.w3.org/2001/XMLSchema">110.12</wd:price>
<wd:copy>0</wd:copy>
</wd:Report_Entry>
<wd:Report_Entry xmlns:wd="http://www.workday.org/">
<wd:id>2000</wd:id>
<wd:name>Metal Slug</wd:name>
<wd:price xmlns:xs="http://www.w3.org/2001/XMLSchema">75</wd:price>
<wd:copy>0</wd:copy>
</wd:Report_Entry>
<wd:Report_Entry xmlns:wd="http://www.workday.org/">
<wd:id>3000</wd:id>
<wd:name>Need For Speed</wd:name>
<wd:price xmlns:xs="http://www.w3.org/2001/XMLSchema">40</wd:price>
<wd:copy>0</wd:copy>
</wd:Report_Entry>
You only need to make a few small changes:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:wd="http://www.workday.org/">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/wd:Report_Data">
<xsl:copy>
<xsl:for-each-group select="wd:Report_Entry" group-by="wd:id">
<xsl:copy>
<xsl:copy-of select="wd:id"/>
<xsl:copy-of select="wd:name"/>
<wd:price>
<xsl:value-of select="sum(current-group()/wd:price)" />
</wd:price>
<xsl:copy-of select="wd:copy"/>
</xsl:copy>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>