Inline xslt for max values per duplicate record

63 views Asked by At

I need to map the following input message instance in my biztalk project so that for every group of customer records the program checks if there are any duplicate debtor info values. If there are duplicate values the Inline XSLT template checks max value of the total sum in repeating records and changes destination invoice info code to value "Al".

Input:

<customer>
<record>
    <Debtor>
        <Debtor_info1>
            <name>Jack</name>
        </Debtor_info1>
        <Debtor_info2>
            <y-value>0123-xxx</y-value>
            <postnumber>Nevada 666</postnumber>
        </Debtor_info2>
    </Debtor>
    <invoice_info>
        <code></code>
        <invoice_address></invoice_address>
        <total_amount>6000</total_amount>
    </invoice_info>
</record>
<record>
    <Debtor>
        <Debtor_info1>
            <name>Jack</name>
        </Debtor_info1>
        <Debtor_info2>
            <y-value>0123-xxx</y-value>
            <postnumber>Nevada 666</postnumber>
        </Debtor_info2>
    </Debtor>
    <invoice_info>
        <code></code>
        <invoice_address></invoice_address>
        <total_amount>3000</total_amount>
    </invoice_info>
</record>
<record>
    <Debtor>
        <Debtor_info1>
            <name>Evelyn</name>
        </Debtor_info1>
        <Debtor_info2>
            <y-value>0123-xxx</y-value>
            <postnumber>Manchester 666</postnumber>
        </Debtor_info2>
    </Debtor>
    <invoice_info>
        <code></code>
        <invoice_address></invoice_address>
        <total_amount>30</total_amount>
    </invoice_info>
</record></customer>

Output:

<customer>
<record>
    <Debtor>
        <Debtor_info1>
            <name>Jack</name>
        </Debtor_info1>
        <Debtor_info2>
            <y-value>0123-xxx</y-value>
            <postnumber>Nevada 666</postnumber>
        </Debtor_info2>
    </Debtor>
    <invoice_info>
        <code>Al</code>
        <invoice_address></invoice_address>
        <total_amount>6000</total_amount>
    </invoice_info>
</record>
<record>
    <Debtor>
        <Debtor_info1>
            <name>Jack</name>
        </Debtor_info1>
        <Debtor_info2>
            <y-value>0123-xxx</y-value>
            <postnumber>Nevada 666</postnumber>
        </Debtor_info2>
    </Debtor>
    <invoice_info>
        <code></code>
        <invoice_address></invoice_address>
        <total_amount>3000</total_amount>
    </invoice_info>
</record>
<record>
    <Debtor>
        <Debtor_info1>
            <name>Evelyn</name>
        </Debtor_info1>
        <Debtor_info2>
            <y-value>0123-xxx</y-value>
            <postnumber>Manchester 666</postnumber>
        </Debtor_info2>
    </Debtor>
    <invoice_info>
        <code></code>
        <invoice_address></invoice_address>
        <total_amount>30</total_amount>
    </invoice_info>
</record></customer>

I have tried achieving this using Muenchian grouping (XSLT 1.0) with one xslt call template and one inline xslt template connected to destination schema as well as other methods with no luck whatsoever. The inline template should use sequence of records to sort and output max value of the total_amount using debtor info values, but so far I haven't been able to achieve desired output. I would really appreciate help in this issue.

1

There are 1 answers

0
michael.hor257k On

I suppose this is one way you could look at it:

XSLT 1.0

<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:strip-space elements="*"/>

<xsl:key name="dup" match="invoice_info" use="../Debtor/Debtor_info1" />

<!-- identity transform -->
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="invoice_info[count(key('dup', ../Debtor/Debtor_info1)) > 1]">
    <xsl:variable name="max-amt">
        <xsl:for-each select="key('dup', ../Debtor/Debtor_info1)">
            <xsl:sort select="total_amount" data-type="number" order="descending"/>
            <xsl:if test="position() = 1">
                <xsl:value-of select="total_amount"/>
            </xsl:if>
        </xsl:for-each>
    </xsl:variable>
    <!-- output -->
    <xsl:copy>
        <xsl:choose>
            <xsl:when test="total_amount = $max-amt">
                <code>A1</code>
            </xsl:when>
            <xsl:otherwise>
                <xsl:apply-templates select="code"/>
            </xsl:otherwise>
        </xsl:choose>
        <xsl:apply-templates select="invoice_address | total_amount"/>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

Note that in case of a tie, all records having the max value will be marked.