Search code examples
xsltxslt-1.0xslt-2.0xslt-grouping

duplicate consideration from source through xslt


input data: below is the input data getting from the source. how we can achieve through XSLT mapping SCPI, Thanks in advance, and looking forward to your response. I have the following problem (which is quite often discussed in this domain but still I can't get the exact solution): I have an XML like the following:

         <orderHeader>
            <distributionChannelCode>10</distributionChannelCode>
            <orderItem>
                <productCode>AQ7481-002-001</productCode>
            </orderItem>
              <orderItem>
                <productCode>AQ7481-002-004</productCode>
            </orderItem>
            <orderItem>
                <productCode>AQ7481-002-001</productCode>
            </orderItem>
            <orderItem>
                <productCode>AQ7481-002-003</productCode>
            </orderItem>
            <orderItem>
                <productCode>AQ7481-002-002</productCode>
            </orderItem>
            <orderItem>
                <productCode>AQ7481-002-003</productCode>
            </orderItem>
            <orderItem>
                <productCode>AQ7481-002-003</productCode>
            </orderItem>
            <orderItem>
                <productCode>AQ7481-002-004</productCode>
            </orderItem>
             <orderItem>
                <productCode>AQ7481-002-002</productCode>
            </orderItem>
        </orderHeader>

Required Output:

<orderHeader>
            <distributionChannelCode>10</distributionChannelCode>
            <orderItem>
                <productCode>AQ7481-002-001</productCode>
            </orderItem>
            <orderItem>
                <productCode>AQ7481-002-002</productCode>
            </orderItem>
            <orderItem>
                <productCode>AQ7481-002-003</productCode>
            </orderItem>
            <orderItem>
                <productCode>AQ7481-002-004</productCode>
            </orderItem>
        </orderHeader>  
        <orderHeader>
            <distributionChannelCode>10</distributionChannelCode>
            <orderItem>
                <productCode>AQ7481-002-001</productCode>
            </orderItem>
             <orderItem>
                <productCode>AQ7481-002-002</productCode>
            </orderItem>
             <orderItem>
                <productCode>AQ7481-002-003</productCode>
            </orderItem>
        </orderHeader>
        <orderHeader>
            <distributionChannelCode>10</distributionChannelCode>
             <orderItem>
                <productCode>AQ7481-002-003</productCode>
            </orderItem>
        </orderHeader>

Solution

  • I am not sure I have understood the logic but perhaps the following which groups orderItems by productCode to establish which group has the most items and then outputs as many orderHeaders with the corresponding item from each group does the job:

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:xs="http://www.w3.org/2001/XMLSchema"
        exclude-result-prefixes="#all"
        version="3.0">
    
      <xsl:mode on-no-match="shallow-copy"/>
    
      <xsl:output method="xml" indent="yes"/>
      <xsl:strip-space elements="*"/>
    
      <xsl:template match="orderHeader">
          <xsl:variable name="groups" as="map(xs:string, element(orderItem)*)*">
              <xsl:for-each-group select="orderItem" group-by="string(productCode)">
                  <xsl:map-entry key="current-grouping-key()" select="current-group()"/>
              </xsl:for-each-group>
          </xsl:variable>
          <xsl:variable name="this" select="."/>
          <xsl:variable name="max-items" select="max($groups!count(?*))"/>
          <xsl:iterate select="1 to $max-items">
              <orderHeader>
                  <xsl:copy-of 
                    select="$this/distributionChannelCode, 
                            $groups ! ?*[current()]"/>
              </orderHeader>
          </xsl:iterate>
      </xsl:template>
      
    </xsl:stylesheet>