how to get unique record count for each location_Name by Record_No when RECORD_TYPE='ERROR' with XSLT

StackOverflow https://stackoverflow.com/questions/12495893

  •  02-07-2021
  •  | 
  •  

Question

how to get unique record count for each location_Name by Record_No when RECORD_TYPE='ERROR'. if there are multiple records with RECORD_TYPE='ERROR' for a RECORD_NO then only one record should be counted for a RECORD_NO and finally all these records should be grouped by LOCATION_NAME below is the xml date

<root>
    <SellOutErrorRecord>
        <RECORD_TYPE>WARNING</RECORD_TYPE>
        <RECORD_NO>1</RECORD_NO>
            <ERROR_DESC>trx doc type is invalid</ERROR_DESC>
        <LOCATION_NAME>Chen Ken</LOCATION_NAME>
        <PRODUCT_NUMBER>336549R-001</PRODUCT_NUMBER>
    </SellOutErrorRecord>
    <SellOutErrorRecord>
        <RECORD_TYPE>ERROR</RECORD_TYPE>
        <RECORD_NO>2</RECORD_NO>
            <ERROR_DESC>invoice amount is zero</ERROR_DESC>
        <LOCATION_NAME>Chen Ken</LOCATION_NAME>
        <PRODUCT_NUMBER>3X-KN73C-DB</PRODUCT_NUMBER>
    </SellOutErrorRecord>
        <SellOutErrorRecord>
        <RECORD_TYPE>ERROR</RECORD_TYPE>
            <ERROR_DESC>sales qty is zero</ERROR_DESC>
        <RECORD_NO>2</RECORD_NO>
        <LOCATION_NAMEChen Ken</LOCATION_NAME>
        <PRODUCT_NUMBER>3X-KN73C-DB</PRODUCT_NUMBER>
    </SellOutErrorRecord>
    <SellOutErrorRecord>
        <RECORD_TYPE>ERROR</RECORD_TYPE>
        <ERROR_DESC>trx currency is invalid</ERROR_DESC>
        <RECORD_NO>3</RECORD_NO>
        <LOCATION_NAME>Chen Ken</LOCATION_NAME>
        <PRODUCT_NUMBER>339112-B25</PRODUCT_NUMBER>
    </SellOutErrorRecord>
    <SellOutErrorRecord>
        <RECORD_TYPE>ERROR</RECORD_TYPE>
        <ERROR_DESC>invoiced net amount is invalid</ERROR_DESC>
        <RECORD_NO>3</RECORD_NO>
        <LOCATION_NAME>Chen Ken</LOCATION_NAME>
        <PRODUCT_NUMBER>445860-B21</PRODUCT_NUMBER>
    </SellOutErrorRecord>
    <SellOutErrorRecord>
        <RECORD_TYPE>ERROR</RECORD_TYPE>
        <ERROR_DESC>invoiced net amount is invalid</ERROR_DESC>
        <RECORD_NO>1</RECORD_NO>
        <LOCATION_NAME>Chen Ken</LOCATION_NAME>
        <PRODUCT_NUMBER>339112-B25</PRODUCT_NUMBER>
    </SellOutErrorRecord>
        <SellOutErrorRecord>
        <RECORD_TYPE>WARNING</RECORD_TYPE>
        <RECORD_NO>1</RECORD_NO>
            <ERROR_DESC>trx doc type is invalid</ERROR_DESC>
        <LOCATION_NAME>Cheng Boon</LOCATION_NAME>
        <PRODUCT_NUMBER>336549R-001</PRODUCT_NUMBER>
    </SellOutErrorRecord>
    <SellOutErrorRecord>
        <RECORD_TYPE>ERROR</RECORD_TYPE>
        <RECORD_NO>2</RECORD_NO>
            <ERROR_DESC>invoice amount is zero</ERROR_DESC>
        <LOCATION_NAME>Cheng Boon</LOCATION_NAME>
        <PRODUCT_NUMBER>3X-KN73C-DB</PRODUCT_NUMBER>
    </SellOutErrorRecord>
        <SellOutErrorRecord>*-
        <RECORD_TYPE>ERROR</RECORD_TYPE>
            <ERROR_DESC>sales qty is zero</ERROR_DESC>
        <RECORD_NO>2</RECORD_NO>
        <LOCATION_NAME>Cheng Boon</LOCATION_NAME>
        <PRODUCT_NUMBER>3X-KN73C-DB</PRODUCT_NUMBER>
    </SellOutErrorRecord>
    <SellOutErrorRecord>
        <RECORD_TYPE>ERROR</RECORD_TYPE>
        <ERROR_DESC>trx currency is invalid</ERROR_DESC>
        <RECORD_NO>3</RECORD_NO>
        <LOCATION_NAME>Cheng Boon</LOCATION_NAME>
        <PRODUCT_NUMBER>339112-B25</PRODUCT_NUMBER>
    </SellOutErrorRecord>
    <SellOutErrorRecord>
        <RECORD_TYPE>ERROR</RECORD_TYPE>
        <ERROR_DESC>invoiced net amount is invalid</ERROR_DESC>
        <RECORD_NO>3</RECORD_NO>
        <LOCATION_NAME>Cheng Boon</LOCATION_NAME>
        <PRODUCT_NUMBER>445860-B21</PRODUCT_NUMBER>
    </SellOutErrorRecord>
</root>

The expected output is:

LOCATION_NAME:Chen Ken COUNT:3
LOCATION_NAME:Cheng Boon COUNT:2
Was it helpful?

Solution

This is a pretty awful solution using for-each and a call template, with the same distincting as done here. You might consider asking your upstream data provider to clean up the data - I'm not sure that XSLT is the best place for 'debouncing' data like this. It's XSLT 1.0.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text" indent="no"/>

    <xsl:template match="/root">
        <xsl:for-each select="*[LOCATION_NAME]">
            <xsl:variable name="LocationName" select="LOCATION_NAME/text()" />
            <xsl:if test="not(following::*[LOCATION_NAME/text()=$LocationName])" >
                <xsl:call-template name="CountGroup">
                    <xsl:with-param name="LocationName" select="$LocationName" />
                </xsl:call-template>
            </xsl:if>
        </xsl:for-each>
    </xsl:template>

    <xsl:template name="CountGroup">
        <xsl:param name="LocationName"></xsl:param>
        LOCATION_NAME:<xsl:value-of select="$LocationName"/>
        COUNT <xsl:value-of select="count(//*[RECORD_TYPE='ERROR' and LOCATION_NAME=$LocationName 
                                              and not(following::*[RECORD_TYPE='ERROR' and LOCATION_NAME=$LocationName]
                                             /RECORD_NO/text() = RECORD_NO/text())])" />

    </xsl:template>
</xsl:stylesheet>

Returns

LOCATION_NAME:Chen Ken COUNT 3
LOCATION_NAME:Cheng Boon COUNT 2
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top