Reputation: 6163
I am trying to sort an xml document in groups. My sample xml is below:
<a>
<b sortKey="e"></b>
<b sortKey="b"></b>
<d sortKey="b"></d>
<d sortKey="a"></d>
<c></c>
</a>
I'd like to sort all the b
s and all the d
s separately. b
and d
may have different sort keys.
I tried many different options based on what I've seen here and other places, but they either only give me the elements that are sorted, or give me the sorted elements + the rest of the elements.
This is one of my attempts:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
>
<xsl:output method="xml" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:choose>
<xsl:when test="*[local-name()='b']">
<xsl:apply-templates select="@* | node()">
<xsl:sort select="@sortKey" />
</xsl:apply-templates>
</xsl:when>
<xsl:when test="*[local-name()='d']">
<xsl:apply-templates select="@* | node()">
<xsl:sort select="@sortKey" />
</xsl:apply-templates>
</xsl:when>
<xsl:otherwise>
</xsl:otherwise>
</xsl:choose>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
This sorted all of the elements with an attribute sortKey
, not the b
s and d
s separately.
I'm a noob with XSLT. so any help is much appreciated
ETA: My desired xml is like this
<a>
<b sortKey="b"></b>
<b sortKey="e"></b>
<d sortKey="a"></d>
<d sortKey="b"></d>
<c></c>
</a>
Upvotes: 0
Views: 1414
Reputation: 116992
Would something like this work for you?
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="a">
<xsl:copy>
<xsl:apply-templates select="b">
<xsl:sort select="@sortKey"/>
</xsl:apply-templates>
<xsl:apply-templates select="d">
<xsl:sort select="@sortKey"/>
</xsl:apply-templates>
<xsl:apply-templates select="*[not(self::b or self::d)]"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Upvotes: 1