Shaibayan Chakrabarti
Shaibayan Chakrabarti

Reputation: 55

Remove duplicate issue using XSLT

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

Answers (1)

Douglas Martins
Douglas Martins

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

Related Questions