Search code examples
xslt-2.0xslt-3.0

XSLT Sort has issues with few Child nodes


I am trying to use XSLT to sort only specific segments when it is having same /HEADER/DOC/E_E20/ROOT/MAT segments, if this case exist then //ROOT/FIELD3 must be used as key to sort the entire segments, other segments we can keep in the same position which they belongs to, i have tried XSLT, its giving exact results, but initial segments under E_E20 (ND2,ND3,L18 which are subsegments of E_E20) are suppressing in output, i tried all the possible ways, Please assist..

Input

<?xml version="1.0" encoding="UTF-8"?>
<HEADER>
    <DOC BEGIN="1">
        <EDI_40>
            <Field1>123</Field1>
        </EDI_40>
        <E_E20>
            <ND2>123</ND2>
            <ND3>345</ND3>
            <L18 SEGMENT="1">
                <QUALF>PGI</QUALF>
            </L18>
            <ROOT SEGMENT="1">
                <POS>000020</POS>
                <MAT>1234</MAT>
                <FIELD3>4199</FIELD3>
                <QUAN>3420</QUAN>
                <CHILD SEGMENT="1">
                    <POS>000010</POS>
                    <PQ>UN</PQ>
                </CHILD>
            </ROOT>
            <ROOT SEGMENT="1">
                <POS>000010</POS>
                <MAT>123456</MAT>
                <FIELD3>4199BI015</FIELD3>
                <QUAN>3420</QUAN>
                <CHILD SEGMENT="1">
                    <POS>000010</POS>
                    <PQ>UN1</PQ>
                </CHILD>
            </ROOT>
            <ROOT SEGMENT="1">
                <POS>000010</POS>
                <MAT>123456</MAT>
                <FIELD3>4184AI015</FIELD3>
                <QUAN>1026</QUAN>
                <CHILD SEGMENT="1">
                    <POS>000010</POS>
                    <PQ>UN2</PQ>
                </CHILD>
                <CHILD SEGMENT="1">
                    <POS>000010</POS>
                    <PQ>UN2</PQ>
                </CHILD>
            </ROOT>
            <ROOT SEGMENT="1">
                <POS>000010</POS>
                <MAT>123456</MAT>
                <FIELD3>4200AI015</FIELD3>
                <QUAN>1197</QUAN>
                <CHILD SEGMENT="1">
                    <POS>000010</POS>
                    <PQ>UN3</PQ>
                </CHILD>
            </ROOT>
            <ROOT SEGMENT="1">
                <POS>000030</POS>
                <MAT>123</MAT>
                <FIELD3>4200AI</FIELD3>
                <QUAN>1197</QUAN>
                <CHILD SEGMENT="1">
                    <POS>000010</POS>
                    <PQ>UN</PQ>
                </CHILD>
            </ROOT>
        </E_E20>
    </DOC>
</HEADER>


**output **

<?xml version="1.0" encoding="UTF-8"?>
<HEADER>
    <DOC BEGIN="1">
        <EDI_40>
            <Field1>123</Field1>
        </EDI_40>
        <E_E20>
            <ND2>123</ND2>
            <ND3>345</ND3>
            <L18 SEGMENT="1">
                <QUALF>PGI</QUALF>
            </L18>
            <ROOT SEGMENT="1">
                <POS>000020</POS>
                <MAT>1234</MAT>
                <FIELD3>4199</FIELD3>
                <QUAN>3420</QUAN>
                <CHILD SEGMENT="1">
                    <POS>000010</POS>
                    <PQ>UN</PQ>
                </CHILD>
            </ROOT>
            <ROOT SEGMENT="1">
                <POS>000010</POS>
                <MAT>123456</MAT>
                <FIELD3>4184AI015</FIELD3>
                <QUAN>1026</QUAN>
                <CHILD SEGMENT="1">
                    <POS>000010</POS>
                    <PQ>UN2</PQ>
                </CHILD>
                <CHILD SEGMENT="1">
                    <POS>000010</POS>
                    <PQ>UN2</PQ>
                </CHILD>
            </ROOT>
            <ROOT SEGMENT="1">
                <POS>000010</POS>
                <MAT>123456</MAT>
                <FIELD3>4199BI015</FIELD3>
                <QUAN>3420</QUAN>
                <CHILD SEGMENT="1">
                    <POS>000010</POS>
                    <PQ>UN1</PQ>
                </CHILD>
            </ROOT>
            <ROOT SEGMENT="1">
                <POS>000010</POS>
                <MAT>123456</MAT>
                <FIELD3>4200AI015</FIELD3>
                <QUAN>1197</QUAN>
                <CHILD SEGMENT="1">
                    <POS>000010</POS>
                    <PQ>UN3</PQ>
                </CHILD>
            </ROOT>
            <ROOT SEGMENT="1">
                <POS>000030</POS>
                <MAT>123</MAT>
                <FIELD3>4200AI</FIELD3>
                <QUAN>1197</QUAN>
                <CHILD SEGMENT="1">
                    <POS>000010</POS>
                    <PQ>UN</PQ>
                </CHILD>
            </ROOT>
        </E_E20>
    </DOC>
</HEADER>


XSLT I used

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="3.0"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  exclude-result-prefixes="#all"
  expand-text="yes">

  <xsl:output method="xml" indent="yes"/>

  <xsl:mode on-no-match="shallow-copy"/>
  
  <xsl:template match="E_E20">
    <xsl:copy>
      <xsl:apply-templates select="@*"/>
      <xsl:for-each-group select="ROOT" group-by="MAT">
        <xsl:apply-templates select="current-group()">
          <xsl:sort select="FIELD3"/>
        </xsl:apply-templates>
      </xsl:for-each-group>
    </xsl:copy>
  </xsl:template>



</xsl:stylesheet>


Solution

  • Change <xsl:apply-templates select="@*"/> to <xsl:apply-templates select="@*, * except ROOT"/>.