jeudi 10 décembre 2020

XSLT 2.0 : picking up XML node by matching one child node and comparing other

I have input XML like below:

<parent>
    <payment>
        <id>123456</id>
        <type>CANCELLED</type>
        <date>2020-12-03</date>
        <amount>100</amount>
    </payment>
    <payment>
        <id>234567</id>
        <type>FORCE</type>
        <date>2020-12-01</date>
        <amount>200</amount>
    </payment>
    <payment>
        <id>345678</id>
        <type>CANCELLED</type>
        <date>2020-12-01</date>
        <amount>300</amount>
    </payment>
    <payment>
        <id>456789</id>
        <type>FORCE</type>
        <date>2020-12-01</date>
        <amount>400</amount>
    </payment>
    <payment>
        <id>456788</id>
        <type>CANCELLED</type>
        <date>2020-12-01</date>
        <amount>500</amount>
    </payment>
</parent>

Now, we want nodes where type = 'CANCELLED' and tricky condition is within these cancelled payments, if date is equal then we need to pick up node with highest id. SO, in above sample input, only 1st and 5th node should be selected. date for first node doesn't match with any other node, so it is selected. While date for 5th node matches with 3rd node but 5th is selected as it has higher id.

To achieve this, I tried to write below XSLT,

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:strip-space elements="*"/>
    <xsl:variable name="input" select="parent"/>
    <xsl:template match="/">
        <xsl:for-each select="parent/payment[type='CANCELLED']">
            <xsl:choose>
                <xsl:when test="date = $input/payment[type='CANCELLED']/date">
                    <xsl:message>
                        <xsl:value-of select="amount"/>
                    </xsl:message>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:value-of select="amount"/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

For-each is required as in actual example we are extracting some values, so we need to tweak for-each loop condition or write if condition inside it. I tried to declare variable input with whole input xml and compare node which is selected within for-each iteration with input node but then it matches with self as well. Am I going in right direction? Please guide.

Thanks in advance.

Aucun commentaire:

Enregistrer un commentaire