user2729074
user2729074

Reputation: 3

XSL to remove duplicate records

I have a requirement where I need to omit duplicate records. Consider sample below

Following is the input

<ExchangeRates>
<Rate>  <!--The exchange rates -->
<SourceCurrency>INR</SourceCurrency>
<TargetCurrency>USD</TargetCurrency>
<ConversionFactor>60.2</ConversionFactor>
</Rate>
<Rate>
<SourceCurrency>INR</SourceCurrency>
<TargetCurrency>USD</TargetCurrency>
<ConversionFactor>58.2</ConversionFactor>
</Rate>
<Rate>
<SourceCurrency>YEN</SourceCurrency>
<TargetCurrency>INR</TargetCurrency>
<ConversionFactor>.52</ConversionFactor>
</Rate>
<Rate>
<SourceCurrency>SAR</SourceCurrency>
<TargetCurrency>INR</TargetCurrency>
<ConversionFactor>16.50</ConversionFactor>
</Rate>
 <Rate>
<SourceCurrency>SAR</SourceCurrency>
<TargetCurrency>INR</TargetCurrency>
<ConversionFactor>16.50</ConversionFactor>
</Rate>
</ExchangeRates>

Now what i wanna do is remove all duplicates. As well as if there is same pair of Source and TargetCurrency , I want to send ahead the first record and drop others.

Output shud be like

<ExchangeRates>
<Rate>
<SourceCurrency>INR</SourceCurrency>
<TargetCurrency>USD</TargetCurrency>
<ConversionFactor>60.2</ConversionFactor>
</Rate>
<Rate>
<SourceCurrency>YEN</SourceCurrency>
<TargetCurrency>INR</TargetCurrency>
<ConversionFactor>.52</ConversionFactor>
</Rate>
<Rate>
<SourceCurrency>SAR</SourceCurrency>
<TargetCurrency>INR</TargetCurrency>
<ConversionFactor>16.50</ConversionFactor>
</Rate>
</ExchangeRates>

I found that following XSLT removes duplicates. ie. if inner elements are exactly same. The below code helps me easily avoid duplicates. It identifies the duplicates based on contents inside the outer tag.

But I want to xslt to remove records if exchange rates come for same pair of currencies but multiple ConversionFactors.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:template match="@*|node()">
        <xsl:if test="not(node()) or not(preceding-sibling::node()[.=string(current())])">
            <xsl:copy>
                <xsl:apply-templates select="@*|node()"/>
            </xsl:copy>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

I need to drop Rates with USD->INR if it occurs multiple times. And forward only the first exchange rate.

Can I get some help in achieving this.

Cheers

Reji

Upvotes: 0

Views: 3061

Answers (1)

Linga Murthy C S
Linga Murthy C S

Reputation: 5432

You need to group Rates based on SourceCurrency and TargetCurrency. An efficient way is using Muenchian's grouping that uses key:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:key name="currencyPair" match="Rate" use="concat(SourceCurrency,' ',TargetCurrency)"/>

<xsl:template match="ExchangeRates">
    <xsl:copy>
        <xsl:for-each select="Rate[count(. | key('currencyPair',concat(SourceCurrency,' ',TargetCurrency))[1]) = 1]">
            <xsl:copy-of select="."/>
        </xsl:for-each>
    </xsl:copy>
</xsl:template>
</xsl:stylesheet>

Upvotes: 2

Related Questions