Reputation: 31
I have a following XML code:
<module>
<component>
<output>
<output-test>
<exclude-output/>
<orderEntry type="specific"/>
<orderEntry type="other"/>
<orderEntry type="module" module-name="module1"/>
<orderEntry type="module" module-name="module3"/>
<orderEntry type="module" module-name="module2"/>
<orderEntry type="library" name="library1"/>
<orderEntry type="library" name="library3"/>
<orderEntry type="module" module-name="module4"/>
<orderEntry type="library" name="library2"/>
</component>
</module>
I would like to have the output:
<module>
<component>
<output>
<output-test>
<exclude-output/>
<orderEntry type="specific"/>
<orderEntry type="other"/>
<orderEntry type="module" module-name="module1"/>
<orderEntry type="module" module-name="module2"/>
<orderEntry type="module" module-name="module3"/>
<orderEntry type="module" module-name="module4"/>
<orderEntry type="library" name="library1"/>
<orderEntry type="library" name="library2"/>
<orderEntry type="library" name="library3"/>
</component>
</module>
Upvotes: 0
Views: 3655
Reputation: 70618
I am not entirely sure if this meets your requirements, but you could explicitly select the ones you want to come first in a separate xsl:apply-templates
, then select the others with a sort on their type
attribute
<xsl:apply-templates select="orderEntry[@type='specific' or @type='other']" />
<xsl:apply-templates select="orderEntry[@type!='specific' and @type!='other']">
<xsl:sort select="@type" order="descending" />
<xsl:sort select="@module-name" order="ascending" />
<xsl:sort select="@name" order="ascending" />
</xsl:apply-templates>
Looking at the current expected output, it seems all the type
attributes are in descending order, so you could simplify it to this
<xsl:apply-templates select="orderEntry">
<xsl:sort select="@type" order="descending" />
<xsl:sort select="@module-name" order="ascending" />
<xsl:sort select="@name" order="ascending" />
</xsl:apply-templates>
Try this XSLT
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="xml" indent="yes" />
<xsl:strip-space elements="*" />
<xsl:template match="component">
<xsl:copy>
<xsl:apply-templates select="@*|node()[not(self::orderEntry)]"/>
<xsl:apply-templates select="orderEntry">
<xsl:sort select="@type" order="descending" />
<xsl:sort select="@module-name" order="ascending" />
<xsl:sort select="@name" order="ascending" />
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Note that, if you actually wanted to sort on type
attribute that were not in alphabetical order, you could do something like this:
<xsl:apply-templates select="orderEntry">
<xsl:sort select="string-length(substring-before('specific,other,module,library',@type))" order="ascending" />
<xsl:sort select="@module-name" order="ascending" />
<xsl:sort select="@name" order="ascending" />
</xsl:apply-templates>
Upvotes: 1