xslt-2.0xslt-3.0

XSLT Missing Segment issue after sorting


I have issue while sorting the segments, i need to sort segments Node/ITEM and Node/LINE segments separately,
Node/ITEM Sorting: we need check if Node/ITEM exist then if Node/ITEM/LINE/FIER/VALUE is repeating in another Node/ITEM/LINE/FIER/Value where Type=Key1,if its repeating then based on ITEM/LINE/FIER/VALUE (Type=Key2) we need to perform sorting. Node/LINE Sorting: Same as above, if Node/LINE exists then based on Node/LINE/FIER/VALUE , we can do sorting.

i found almost similar example, but XSLT is removing Node/LINE Completely, its able to do Node/ITEM sorting correctly. Please review it once

Input:

<SBD>
    <DOCUMENT>
        <Field1> value1</Field1>
    </DOCUMENT>
    <Node documentStatus="True" date="2024-09-27">
        <ship>123</ship>
        <field2>345r</field2>
        <ITEM>
            <IDENT>
                <CODE>
                    <Value>67896789</Value>
                </CODE>
            </IDENT>
            <LINE number="1">
                <CIDENT>
                    <name>12</name>
                    <FIER>
                        <VALUE>555</VALUE>
                        <TYPE>Key1</TYPE>
                    </FIER>
                    <FIER>
                        <VALUE>XYZ</VALUE>
                        <TYPE>Key2</TYPE>
                    </FIER>
                </CIDENT>
            </LINE>
        </ITEM>
        <ITEM>
            <IDENT>
                <CODE>
                    <Value>3243</Value>
                </CODE>
            </IDENT>
            <LINE number="2">
                <CIDENT>
                    <name>12</name>
                    <FIER>
                        <VALUE>444</VALUE>
                        <TYPE>Key1</TYPE>
                    </FIER>
                    <FIER>
                        <VALUE>BBBB</VALUE>
                        <TYPE>Key2</TYPE>
                    </FIER>
                </CIDENT>
            </LINE>
            <Segment1>
                <subsegment>
                    <value>123</value>
                </subsegment>
            </Segment1>
        </ITEM>
        <ITEM>
            <IDENT>
                <CODE>
                    <Value>0870</Value>
                </CODE>
            </IDENT>
            <LINE number="3">
                <CIDENT>
                    <name>12</name>
                    <FIER>
                        <VALUE>444</VALUE>
                        <TYPE>Key1</TYPE>
                    </FIER>
                    <FIER>
                        <VALUE>No</VALUE>
                        <TYPE>Key3</TYPE>
                    </FIER>
                    <FIER>
                        <VALUE>AAA</VALUE>
                        <TYPE>Key2</TYPE>
                    </FIER>
                </CIDENT>
            </LINE>
        </ITEM>
        <LINE number="1">
            <CIDENT>
                <name>12</name>
                <FIER>
                    <VALUE>6382</VALUE>
                    <TYPE>Key1</TYPE>
                </FIER>
                <FIER>
                    <VALUE>REA</VALUE>
                    <TYPE>Key2</TYPE>
                </FIER>
            </CIDENT>
        </LINE>
        <LINE number="2">
            <CIDENT>
                <name>12</name>
                <FIER>
                    <VALUE>5678</VALUE>
                    <TYPE>Key1</TYPE>
                </FIER>
                <FIER>
                    <VALUE>CBA</VALUE>
                    <TYPE>Key2</TYPE>
                </FIER>
            </CIDENT>
        </LINE>      
        <LINE number="3">
            <CIDENT>
                <name>12</name>
                <FIER>
                    <VALUE>5678</VALUE>
                    <TYPE>Key1</TYPE>
                </FIER>
                <FIER>
                    <VALUE>BCA</VALUE>
                    <TYPE>Key2</TYPE>
                </FIER>
            </CIDENT>
        </LINE>
        <rdtime>123</rdtime>
           <advice>123</advice>
        <newfield>213</newfield>
    </Node>
</SBD>



Desired output:

<SBD>
    <DOCUMENT>
        <Field1> value1</Field1>
    </DOCUMENT>
    <Node documentStatus="True" date="2024-09-27">
        <ship>123</ship>
        <field2>345r</field2>
        <ITEM>
            <IDENT>
                <CODE>
                    <Value>67896789</Value>
                </CODE>
            </IDENT>
            <LINE number="1">
                <CIDENT>
                    <name>12</name>
                    <FIER>
                        <VALUE>555</VALUE>
                        <TYPE>Key1</TYPE>
                    </FIER>
                    <FIER>
                        <VALUE>XYZ</VALUE>
                        <TYPE>Key2</TYPE>
                    </FIER>
                </CIDENT>
            </LINE>
        </ITEM>
        <ITEM>
            <IDENT>
                <CODE>
                    <Value>0870</Value>
                </CODE>
            </IDENT>
            <LINE number="3">
                <CIDENT>
                    <name>12</name>
                    <FIER>
                        <VALUE>444</VALUE>
                        <TYPE>Key1</TYPE>
                    </FIER>
                    <FIER>
                        <VALUE>No</VALUE>
                        <TYPE>Key3</TYPE>
                    </FIER>
                    <FIER>
                        <VALUE>AAA</VALUE>
                        <TYPE>Key2</TYPE>
                    </FIER>
                </CIDENT>
            </LINE>
        </ITEM>
        <ITEM>
            <IDENT>
                <CODE>
                    <Value>3243</Value>
                </CODE>
            </IDENT>
            <LINE number="2">
                <CIDENT>
                    <name>12</name>
                    <FIER>
                        <VALUE>444</VALUE>
                        <TYPE>Key1</TYPE>
                    </FIER>
                    <FIER>
                        <VALUE>BBBB</VALUE>
                        <TYPE>Key2</TYPE>
                    </FIER>
                </CIDENT>
            </LINE>
            <Segment1>
                <subsegment>
                    <value>123</value>                  
                </subsegment>
            </Segment1>
        </ITEM>
        <LINE number="1">
            <CIDENT>
                <name>12</name>
                    <FIER>
                    <VALUE>6382</VALUE>
                    <TYPE>Key1</TYPE>
                </FIER>
                <FIER>
                    <VALUE>REA</VALUE>
                    <TYPE>Key2</TYPE>
                </FIER>
        </CIDENT>
    </LINE>
    <LINE number="3">
        <CIDENT>
            <name>12</name>
            <FIER>
                <VALUE>5678</VALUE>
                <TYPE>Key1</TYPE>
            </FIER>
            <FIER>
                <VALUE>BCA</VALUE>
                <TYPE>Key2</TYPE>
            </FIER>
        </CIDENT>
    </LINE>
    <LINE number="2">
        <CIDENT>
            <name>12</name>
            <FIER>
                <VALUE>5678</VALUE>
                <TYPE>Key1</TYPE>
            </FIER>
            <FIER>
                <VALUE>CBA</VALUE>
                <TYPE>Key2</TYPE>
            </FIER>
        </CIDENT>
    </LINE>
    <rdtime>123</rdtime>
   <advice>123</advice>
    <newfield>213</newfield>
</Node>
</SBD>

XSLT I used is below:

<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">
  
  <xsl:output method="xml" indent="yes"/>
  
  <xsl:mode on-no-match="shallow-copy"/>
  
  <xsl:template match="Node">
    <xsl:copy>
      <xsl:apply-templates select="* except (ITEM, LINE, rdtime)"/>
      <xsl:for-each-group select="ITEM" group-by="LINE/CIDENT/FIER[TYPE='Key1']/VALUE">
        <xsl:sequence select="sort(current-group(), (), function($l) { $l/LINE/CIDENT/FIER[TYPE='Key2']/VALUE })" />
      </xsl:for-each-group>
      <xsl:for-each-group select="LINE" group-by="CIDENT/FIER[TYPE='Key1']/VALUE">
        <xsl:sequence select="sort(current-group(), (), function($l) { $l/CIDENT/FIER[TYPE='Key2']/VALUE })" />
      </xsl:for-each-group>
      <xsl:apply-templates select="rdtime,advice,newfield"/>
    </xsl:copy>
  </xsl:template> 
</xsl:stylesheet>

Please review it once


Solution

  • I think if you know the two child elements you want to group and/or sort and the other elements are in a known position you can just make sure you process them all separately and of course you can apply-templates to the attributes of Node:

      <xsl:template match="Node">
        <xsl:copy>
          <xsl:apply-templates select="@*, * except (ITEM, LINE, rdtime, advice, newfield)"/>
          <xsl:for-each-group select="ITEM" group-by="LINE/CIDENT/FIER[TYPE='Key1']/VALUE">
            <xsl:sequence select="sort(current-group(), (), function($l) { $l/LINE/CIDENT/FIER[TYPE='Key2']/VALUE })" />
          </xsl:for-each-group>
          <xsl:for-each-group select="LINE" group-by="CIDENT/FIER[TYPE='Key1']/VALUE">
            <xsl:sequence select="sort(current-group(), (), function($l) { $l/CIDENT/FIER[TYPE='Key2']/VALUE })" />
          </xsl:for-each-group>
          <xsl:apply-templates select="rdtime, advice, newfield"/>
        </xsl:copy>
      </xsl:template>