You are close to the correct solution, but there are a few issues:
<xsl:param name="sortBy" select="viewCount"/>
This defines the $sortBy
parameter as the value of the viewCount
child of the current node (the document node). Because the top element is not named viewCount
, the $sortBy
parameter so defined has no value at all.
<xsl:param name="order" select="descending"/>
Ditto.
<xsl:sort select="$sortBy" order="$order"/>
Even if issues 1. and 2. above are fixed, this xslt instruction is still problematic. It specifies the value of the order
attribute as the literal string '$order'
-- not as the value of the parameter $order
. The way to do this in XSLT is by using AVT (Attribute Value Template). Whenever we want a to specify that within an attribute value we want a particular string to be evaluated as an XPath expression, then this string must be surrounded by curly braces.
So, the order
attribute should be specified as: order = '{$order}'
.
Unfortunately, AVTs cannot be used for the select
attribute (another rule from the XSLT spec).
The way to specify the value of the select
attribute is a little-bit more tricky:
select='*[name()=$sortBy]'
This says: sort by the child element, whose name is the same as the value of the variable $sortBy
.
To put all this together, here is the corrected transformation:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="sortBy" select="'viewCount'"/>
<xsl:param name="order" select="'descending'"/>
<xsl:template match="/">
<media>
<xsl:for-each select="media/medium">
<xsl:sort select="*[name()=$sortBy]" order="{$order}"/>
<xsl:copy-of select="."/>
</xsl:for-each>
</media>
</xsl:template>
</xsl:stylesheet>
When this transformation is applied on the following XML document:
<media>
<medium>
<viewCount>2</viewCount>
</medium>
<medium>
<viewCount>1</viewCount>
</medium>
<medium>
<viewCount>5</viewCount>
</medium>
</media>
The correct result is produced:
<media>
<medium>
<viewCount>5</viewCount>
</medium>
<medium>
<viewCount>2</viewCount>
</medium>
<medium>
<viewCount>1</viewCount>
</medium>
</media>