xmlxsltxslt-2.0

As per the channel number order the value should pick


I need to pick the value as per the channel number order from the input xml

<Rates>
    <Rate>
        <Channel>1</Channel>
        <Type>Life</Type>
        <GRates>
            <GRate>
                <band>&lt;25</band>
                <amount>0.04</amount>
            </GRate>
        </GRates>
    </Rate>
    <Rate>
        <Channel>2</Channel>
        <Type>Life</Type>
        <GRates>
            <GRate>
                <band>&lt;25</band>
                <amount>0.12</amount>
            </GRate>
        </GRates>
    </Rate>
    <Rate>
        <Channel>1</Channel>
        <Type>Add</Type>
        <GRates>
            <GRate>
                <band>&lt;25</band>
                <amount>0.08</amount>
            </GRate>
        </GRates>
    </Rate>
</Rates>

XSL I have tried the below:

<xsl:template match="/Rates">
    <xsl:for-each-group select="Rate[Channel=('1', '2')][Type=('Life', 'Add')]/GRates/GRate" group-by="band">
        <row>
            <entry align="center" colsep="1">
                <xsl:value-of select="band"/>
            </entry>
            <xsl:for-each select="current-group()">
                <entry>
                    <p>
                        <xsl:value-of select="format-number(amount, '$0.00')"/>
                    </p>
                </entry>
            </xsl:for-each>
        </row>
    </xsl:for-each-group>
</xsl:template>

Output I'm gettng:

<row>
    <entry align="center" colsep="1">&lt;25</entry>
    <entry>
        <p>$0.04</p>
    </entry>
    <entry>
        <p>$0.12</p>
    </entry>
    <entry>
        <p>$0.08</p>
    </entry>
</row>

Expected output is:

<row>
    <entry align="center" colsep="1">&lt;25</entry>
    <entry>
        <p>$0.04</p>
    </entry>
    <entry>
        <p>$0.08</p>
    </entry>
    <entry>
        <p>$0.12</p>
    </entry>
    <entry>
        <p>NA</p>
    </entry>
</row>

The Channel 1 of 'Lif' and 'Add' rates amount should be the first set of row entry and Channel 2 should be the 2nd set of row entry. In case if the element of 'Life' or 'Add' of any channel number is not available, then that output should be 'NA'


Solution

  • It is very difficult to understand from a single example what are the rules that need to be applied here.

    Assuming that inside each group by band there cannot be more than one Rate in each one of the 4 categories by Channel and Type, you could do:

    <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes"/>
    
    <xsl:template match="/Rates">
        <xsl:for-each-group select="Rate/GRates/GRate" group-by="band">
            <row>
                <entry align="center" colsep="1">
                    <xsl:value-of select="band"/>
                </entry>
    
                <xsl:call-template name="entry">
                    <xsl:with-param name="rate" select="current-group()[../../(Channel='1' and Type='Life')]" />
                </xsl:call-template>
                
                <xsl:call-template name="entry">
                    <xsl:with-param name="rate" select="current-group()[../../(Channel='1' and Type='Add')]" />
                </xsl:call-template>
    
                <xsl:call-template name="entry">
                    <xsl:with-param name="rate" select="current-group()[../../(Channel='2' and Type='Life')]" />
                </xsl:call-template>
    
                <xsl:call-template name="entry">
                    <xsl:with-param name="rate" select="current-group()[../../(Channel='2' and Type='Add')]" />
                </xsl:call-template>
            </row>
        </xsl:for-each-group>
    </xsl:template>
    
    <xsl:template name="entry">
        <xsl:param name="rate"/>
        <entry>
            <p>
                <xsl:value-of select="if($rate) then format-number($rate/amount, '$0.00') else 'NA'"/>
            </p>
        </entry>
    </xsl:template>
    
    </xsl:stylesheet>