Search code examples
xsltxslt-1.0

XSLT mapping to sort the segment based on field value


I am trying to write XSLT1.0 to sort the child segment based on field <KEY>, i am unable to sort it,

there will be multiple <CHILD> segments, we need to sorting based on field <KEY> without deleting the subsegments like <ITEM>

Input sample

<?xml version="1.0" encoding="UTF-8"?>
<HEADER>
    <CODI BEGIN="1">
        <DC40 SEGMENT="1">
            <TABNAM>DC40</TABNAM>
        </DC40>
        <BODY SEGMENT="1">
            <BLDAT>20240503</BLDAT>
            <CHILD SEGMENT="1">
                <RNTAM>68850363</RNTAM>
                <KEY>900030</KEY>
                <ITEM SEGMENT="1">
                    <NAE11>0000000000000</NAE11>
                </ITEM>
            </CHILD>
            <CHILD SEGMENT="1">
                <RNTAM>68850363</RNTAM>
                <KEY>900020</KEY>
                <ITEM SEGMENT="1">
                    <NAE11>0000000001000</NAE11>
                </ITEM>
            </CHILD>
            <CHILD SEGMENT="1">
                <RNTAM>68850792</RNTAM>
                <KEY>900010</KEY>
                <ITEM SEGMENT="1">
                    <NAE11>0000010000000</NAE11>
                </ITEM>
                <ITEM SEGMENT="1">
                    <NAE11>0000000030000</NAE11>
                </ITEM>     
            </CHILD>        
        </BODY>
    </CODI>
</HEADER>

output sample

<?xml version="1.0" encoding="UTF-8"?>
<HEADER>
    <CODI BEGIN="1">
        <DC40 SEGMENT="1">
            <TABNAM>DC40</TABNAM>
        </DC40>
        <BODY SEGMENT="1">
            <BLDAT>20240503</BLDAT>         
            <CHILD SEGMENT="1">
                <RNTAM>68850792</RNTAM>
                <KEY>900010</KEY>
                <ITEM SEGMENT="1">
                    <NAE11>0000010000000</NAE11>
                </ITEM>
                <ITEM SEGMENT="1">
                    <NAE11>0000000030000</NAE11>
                </ITEM>             
            </CHILD>            
            <CHILD SEGMENT="1">
                <RNTAM>68850363</RNTAM>
                <KEY>900020</KEY>
                <ITEM SEGMENT="1">
                    <NAE11>0000000001000</NAE11>
                </ITEM>
            </CHILD>            
            <CHILD SEGMENT="1">
                <RNTAM>68850363</RNTAM>
                <KEY>900030</KEY>
                <ITEM SEGMENT="1">
                    <NAE11>0000000000000</NAE11>
                </ITEM>
            </CHILD>            
        </BODY>
    </CODI>
</HEADER>

I have attempted below code, can you please assist here.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="HEADER">
        <xsl:copy>
            <xsl:apply-templates select="HEADER/CODI/BODY/CHILD"/>
            <xsl:sort select="CHILD()"/>
            <xsl:copy-of select="."/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

Solution

  • I think you want:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>
    
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    
    <xsl:template match="BODY">
        <xsl:copy>
            <xsl:apply-templates select="@* | BLDAT"/>
            <xsl:apply-templates select="CHILD">
                <xsl:sort select="KEY"/>
            </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>
    
    </xsl:stylesheet>