Вы близки к правильному решению , но есть несколько проблем:
<xsl:param name="sortBy" select="viewCount"/>
Это определяет параметр $sortBy
как значение дочернего элемента viewCount
текущего узла (узла документа). Поскольку верхний элемент не называется viewCount
, определенный таким образом параметр $sortBy
не имеет значения вообще.
<xsl:param name="order" select="descending"/>
То же самое.
<xsl:sort select="$sortBy" order="$order"/>
Даже если проблемы 1. и 2. выше устранены, эта инструкция xslt все еще проблематична. Он указывает значение атрибута order
в виде буквенной строки '$order'
, а не в качестве значения параметра $order
. Способ сделать это в XSLT - использовать AVT (шаблон значений атрибутов). Всякий раз, когда мы хотим указать, что в значении атрибута мы хотим, чтобы определенная строка была оценена как выражение XPath, эта строка должна быть заключена в фигурные скобки.
Итак, атрибут order
должен быть указан как: order = '{$order}'
.
К сожалению, AVT нельзя использовать для атрибута select
(другое правило из спецификации XSLT).
Способ указать значение атрибута select
немного сложнее:
select='*[name()=$sortBy]'
Это говорит: сортировка по дочернему элементу, имя которого совпадает со значением переменной $sortBy
.
Чтобы сложить все вместе, вот исправленное преобразование :
<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>
Когда это преобразование применяется к следующему документу XML :
<media>
<medium>
<viewCount>2</viewCount>
</medium>
<medium>
<viewCount>1</viewCount>
</medium>
<medium>
<viewCount>5</viewCount>
</medium>
</media>
Получен правильный результат :
<media>
<medium>
<viewCount>5</viewCount>
</medium>
<medium>
<viewCount>2</viewCount>
</medium>
<medium>
<viewCount>1</viewCount>
</medium>
</media>