Reputation: 55
I have the below XML.`
<?xml version="1.0" encoding="UTF-8"?>
<ns0:Rates xmlns:ns0="urn:test.com:Bloomberg:ExchangeRate">
<ExchangeRates>
<Header>
<App>FxApp</App>
<Entity>Rate</Entity>
<ProcessedDate>20200820</ProcessedDate>
</Header>
<ExchangeRate>
<RateType>Corporate</RateType>
<From>USD</From>
<To>CHF</To>
<ValidFromDate>20200820</ValidFromDate>
<Conversion>.91</Conversion>
</ExchangeRate>
<ExchangeRate>
<RateType>Corporate</RateType>
<From>INR</From>
<To>EUR</To>
<ValidFromDate>20200820</ValidFromDate>
<Conversion>0.11</Conversion>
</ExchangeRate>
<ExchangeRate>
<RateType>Corporate</RateType>
<From>USD</From>
<To>CHF</To>
<ValidFromDate>20200820</ValidFromDate>
<Conversion>0.91029</Conversion>
</ExchangeRate>
</ExchangeRates>
</ns0:Rates>
In this rates XML we have a Header and then the ExchangeRate set. From this set, we need to remove the duplicate one. For this case USD-CHF rate with Conversion as 0.91029. So the expected outcome would be as below.
<?xml version="1.0" encoding="UTF-8"?>
<ns0:Rates xmlns:ns0="urn:test.com:Bloomberg:ExchangeRate">
<ExchangeRates>
<Header>
<App>FxApp</App>
<Entity>Rate</Entity>
<ProcessedDate>20200820</ProcessedDate>
</Header>
<ExchangeRate>
<RateType>Corporate</RateType>
<From>USD</From>
<To>CHF</To>
<ValidFromDate>20200820</ValidFromDate>
<Conversion>.91</Conversion>
</ExchangeRate>
<ExchangeRate>
<RateType>Corporate</RateType>
<From>INR</From>
<To>EUR</To>
<ValidFromDate>20200820</ValidFromDate>
<Conversion>0.11</Conversion>
</ExchangeRate>
</ExchangeRates>
</ns0:Rates>
I am trying to use the below XSLT logic.
<xsl:stylesheet version="1.0" exclude-result-prefixes="xsl xsd" xmlns:ns="urn:test.com:Bloomberg:ExchangeRate" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsl:template match="/">
<ns:Rates>
<xsl:for-each select="/ns:Rates/ExchangeRates/ExchangeRate[not(RateType=following::RateType)]">
<xsl:sort select="./ValidFromDate" order="ascending"/>
<ExchangeRate>
<xsl:copy-of select="./RateType"/>
<xsl:copy-of select="./From"/>
<xsl:copy-of select="./To"/>
<xsl:copy-of select="./ValidFromDate"/>
<xsl:copy-of select="./Conversion"/>
</ExchangeRate>
</xsl:for-each>
</ns:Rates>
</xsl:template>
</xsl:stylesheet>
With this the output is behaving in a random manner and also removing the Header. Something like the below is what I am getting. The INR-EUR pair for some reason also got removed unexpectedly.
<?xml version="1.0" encoding="UTF-8"?>
<ns0:Rates xmlns:ns0="urn:test.com:Bloomberg:ExchangeRate">
<ExchangeRates>
<ExchangeRate>
<RateType>Corporate</RateType>
<From>USD</From>
<To>CHF</To>
<ValidFromDate>20200820</ValidFromDate>
<Conversion>.91</Conversion>
</ExchangeRate>
</ExchangeRates>
</ns0:Rates>
Any suggestions or fixes will be appreciated.
Upvotes: 1
Views: 44
Reputation: 86
I would do a grouping on the selected fields you want. Then I would do a for-each group so the duplicated would be eliminated.
<xsl:stylesheet version="1.0" exclude-result-prefixes="xsl xsd" xmlns:ns="urn:test.com:Bloomberg:ExchangeRate" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsl:key name="GroupRate" match="/ns:Rates/ExchangeRates/ExchangeRate" use="concat(RateType, From, To)" />
<xsl:template match="/">
<ns:Rates>
<Header>
<App><xsl:value-of select="/ns:Rates/ExchangeRates/Header/App"/></App>
<Entity><xsl:value-of select="/ns:Rates/ExchangeRates/Header/Entity"/></Entity>
<ProcessedDate><xsl:value-of select="/ns:Rates/ExchangeRates/Header/ProcessedDate"/></ProcessedDate>
</Header>
<xsl:for-each select="/ns:Rates/ExchangeRates/ExchangeRate[generate-id() = generate-id(key('GroupRate', concat(RateType, From, To))[1])]">
<ExchangeRate>
<xsl:copy-of select="node()"/>
</ExchangeRate>
</xsl:for-each>
</ns:Rates>
</xsl:template>
</xsl:stylesheet>
Upvotes: 1