Вы можете сделать это:
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
<xsl:output method="xml" encoding="utf-8" />
<xsl:template match="/root">
<xsl:for-each select="item">
<!-- be sure to include every possible value of <rating>! -->
<xsl:sort select="
concat(
substring('4', 1, rating = 'good' ),
substring('3', 1, rating = 'medioce' ),
substring('2', 1, rating = 'bad' ),
substring('1', 1, rating = 'abyssmal' ),
substring('4', 1, rating = '4' ),
substring('3', 1, rating = '3' ),
substring('2', 1, rating = '2' ),
substring('1', 1, rating = '1' )
)
" order="descending" />
<xsl:copy-of select="." />
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
С входом:
<root>
<item>
<name>ABC</name>
<rating>abyssmal</rating>
</item>
<item>
<name>GEH</name>
<rating>bad</rating>
</item>
<item>
<name>DEF</name>
<rating>good</rating>
</item>
<item>
<name>IJK</name>
<rating>medioce</rating>
</item>
</root>
Я получаю:
<item>
<name>DEF</name>
<rating>good</rating>
</item>
<item>
<name>IJK</name>
<rating>medioce</rating>
</item>
<item>
<name>GEH</name>
<rating>bad</rating>
</item>
<item>
<name>ABC</name>
<rating>abyssmal</rating>
</item>
Для объяснения см. Мой другой ответ . ; -)
EDIT
Изменено решение после этого комментария ОП:
Мне нужно использовать рейтинг (с
строки заменены на целые числа), 3
время:
- сделать ключ с
<xsl:key ...
используя рейтинг
- Сортировать предметы по рейтингу
- Распечатать рейтинг.
На каждом шаге я должен использовать рейтинг
ПОСЛЕ замены, (т.е. с использованием целого числа
баллы). Я сделал это, повторяя
concat(...)
код 3 раза, но как вы
видно это не слишком круто ... я
хотел бы найти способ разместить
concat (...)
один раз, без необходимости
повтори это.
Следующее решение XSLT 1.0 выполняет все эти запросы:
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:tmp="http://tempuri.org/"
exclude-result-prefixes="tmp"
>
<xsl:output method="xml" encoding="utf-8" />
<!-- prepare a list of possible ratings for iteration -->
<tmp:ratings>
<tmp:rating num="1" />
<tmp:rating num="2" />
<tmp:rating num="3" />
<tmp:rating num="4" />
</tmp:ratings>
<!-- index items by their rating -->
<xsl:key
name="kItemByRating"
match="item"
use="concat(
substring('4', 1, rating = 'good' ),
substring('3', 1, rating = 'medioce' ),
substring('2', 1, rating = 'bad' ),
substring('1', 1, rating = 'abyssmal' ),
substring('4', 1, rating = '4' ),
substring('3', 1, rating = '3' ),
substring('2', 1, rating = '2' ),
substring('1', 1, rating = '1' )
)
" />
<!-- we're going to need that later-on -->
<xsl:variable name="root" select="/" />
<xsl:template match="/root">
<!-- iterate on the prepared list of ratings -->
<xsl:apply-templates select="document('')/*/tmp:ratings/tmp:rating">
<xsl:sort select="@num" order="descending" />
</xsl:apply-templates>
</xsl:template>
<xsl:template match="tmp:rating">
<xsl:variable name="num" select="@num" />
<!--
The context node is part of the XSL file now. As a consequence,
a call to key() would be evaluated within the XSL file.
The for-each is a means to change the context node back to the
XML file, so that the call to key() can return <item> nodes.
-->
<xsl:for-each select="$root">
<!-- now pull out all items with a specific rating -->
<xsl:apply-templates select="key('kItemByRating', $num)">
<!-- note that we use the variable here! -->
<xsl:with-param name="num" select="$num" />
<xsl:sort select="@name" />
</xsl:apply-templates>
</xsl:for-each>
</xsl:template>
<xsl:template match="item">
<xsl:param name="num" select="''" />
<xsl:copy>
<!-- print out the numeric rating -->
<xsl:attribute name="num">
<xsl:value-of select="$num" />
</xsl:attribute>
<xsl:copy-of select="node() | @*" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>