Reputation: 111
I already have a XSL that sorts my whole Document depending on the attribute values @id or @category. Now i want to enhance it by defining nodes that never should be sorted.
Here is a sample XML:
<root>
[several levels of xml open]
<elemetsToBeSorted>
<sortMe id="8" />
<sortMe id="2" />
<sortMe id="4" />
</elemetsToBeSorted>
<elemetsNOTToBeSorted>
<dontSortMe id="5" />
<dontSortMe id="3" />
<dontSortMe id="2" />
</elemetsNOTToBeSorted>
[several levels of xml closing]
</root>
This is my XSL:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<!-- Sort all Elements after their id or category -->
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()">
<xsl:sort select="@id" />
<xsl:sort select="@category" />
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<!-- Next two templates clean up formatting after sorting -->
<xsl:template match="text()[not(string-length(normalize-space()))]" />
<xsl:template match="text()[string-length(normalize-space()) > 0]">
<xsl:value-of select="translate(.,'

', ' ')" />
</xsl:template>
Expected Ouput:
<root>
[several levels of xml open]
<elemetsToBeSorted>
<sortMe id="2" />
<sortMe id="4" />
<sortMe id="8" />
</elemetsToBeSorted>
<elemetsNOTToBeSorted>
<dontSortMe id="5" />
<dontSortMe id="3" />
<dontSortMe id="2" />
</elemetsNOTToBeSorted>
[several levels of xml closing]
</root>
How can i achieve that my XSL ignores the "elementsNOTToBeSorted" ?
EDIT: I have hundreds of elements that should be sorted, but only a few elements (and its childs) that should not be sorted. So logic would be something like "sort all, except a and b"
Upvotes: 3
Views: 1646
Reputation: 31610
Adding this line should ignore all descendants elements of elementsNOTToBeSorted:
<xsl:template match="elemetsNOTToBeSorted" />
if you want these elements still to be present in the output document you can just copy them instead of suppressing:
<xsl:template match="elemetsNOTToBeSorted">
<xsl:copy-of select="." />
</xsl:template>
Upvotes: 0
Reputation: 338228
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()" />
</xsl:copy>
</xsl:template>
<!-- all elements except a few sort their children -->
<xsl:template match="*[not(self::elemetsNOTToBeSorted | self::otherElemetsNOTToBeSorted)]">
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:apply-templates>
<xsl:sort select="@id" />
<xsl:sort select="@category" />
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<!-- ... -->
Note that match expression specificity plays a role here. The more specific match expression determines which template will run:
node()
is less specific than *
, so element nodes will be handled by <xsl:template match="*">
self::elemetsNOTToBeSorted | self::otherElemetsNOTToBeSorted
will be handled by the identity template.Upvotes: 2