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
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>