<xsl:sort> XSLT

При преобразовании документа элементами xsl:for-each и xsl:apply-templates, выбранные узлы по умолчанию обрабатываются в порядке просмотра документа, который зависит от выражения, использованного в атрибуте select этих элементов. XSLT позволяет изменять этот порядок посредством использования механизма сортировки.

Элементы xsl:for-each и xsl:apply-templates могут содержать один или несколько элементов xsl:sort, которые позволяют предварительно сортировать обрабатываемое множество узлов.

Синтаксис

XSLT 1.0

<xsl:sort
    select = "string-expression"
    lang = "nmtoken"
    data-type = "text | number | qname-but-not-ncname"
    order = "ascending | descending"
    case-order = "upper-first | lower-first" />

Атрибуты

  • selectобязательный атрибут, значением которого является выражение, называемое также ключевым выражением. Это выражение вычисляется для каждого узла обрабатываемого множества, преобразуется в строку и затем используется как значение ключа при сортировке. По умолчанию значением этого атрибута является “.”, что означает, что в качестве значения ключа для каждого узла используется его строковое значение.
  • orderнеобязательный атрибут, определяет порядок, в котором узлы должны сортироваться по своим ключам. Этот атрибут может принимать только два значения — “ascending”, указывающее на восходящий порядок сортировки, и “descending”, указывающее на нисходящий порядок. Значением по умолчанию является “ascending”, то есть восходящий порядок.
  • langнеобязательный атрибут, определяет язык ключей сортировки. Дело в том, что в разных языках символы алфавита могут иметь различный порядок, что, соответственно, должно учитываться при сортировке. Атрибут lang в XSLT может иметь те же самые значения, что и атрибут xml:lang (например: “en”, “en-us”, “ru” и т. д.). Если значение этого атрибута не определено, процессор может либо определять язык исходя из параметров системы, либо сортировать строки исходя из порядка кодов символов Unicode.
  • data-typeнеобязательный атрибут, определяет тип данных, который несут строковые значения ключей. Техническая рекомендация XSLT разрешает этому атрибуту иметь следующие значения:
    • text” — ключи должны быть отсортированы в лексикографическом порядке исходя из языка, определенного атрибутом lang или параметрами системы. Это значение используется по умолчанию;
    • number” — ключи должны сравниваться в численном виде. Если строковое значение ключа не является числом, оно будет преобразовано к не-числу (NaN), и, поскольку нечисловые значения неупорядочены, соответствующий узел может появиться в отсортированном множестве где угодно;
    • имя” — в целях расширяемости XSLT также позволяет указывать в качестве типа данных произвольное имя. В этом случае реализация сортировки полностью зависит от процессора.
  • case-orderнеобязательный атрибут, указывает на порядок сортировки символов разных регистров. Значениями этого атрибута могут быть “upper-first”, что означает, что заглавные символы должны идти первыми, или “lower-first”, что означает, что первыми должны быть строчные символы. К примеру, строки “ночь”, “Улица”, “фонарь”, “Аптека”, “НОЧЬ”, “Фонарь” при использовании case-order="upper-first" будут иметь порядок “Аптека”, “НОЧЬ”, “ночь”, “Фонарь”, “фонарь”, “улица”. При использовании case-order="lower-first" те же строки будут идти в порядке “Аптека”, “ночь”, “НОЧЬ”, “фонарь”, “Фонарь”, “улица”. Значение case-order по умолчанию зависит от процессора и языка сортировки. В большинстве случаев заглавные буквы идут первыми.

Спецификация

XSLT 2.0 и XSLT 3.0

<xsl:sort
    select? = expression
    lang? = { nmtoken }
    order? = { "ascending" | "descending" }
    collation? = { uri }
    stable? = { "yes" | "no" }
    case-order? = { "upper-first" | "lower-first" }
    data-type? = { "text" | "number" | qname-but-not-ncname }>
    <!-- Content: sequence-constructor -->
</xsl:sort>

Описание и примеры

В случае если xsl:for-each и xsl:apply-templates содержат элементы xsl:sort, обработка множества узлов должна производиться не в порядке просмотра документа, а в порядке, который определяется ключами, вычисленными при помощи xsl:sort. Первый элемент xsl:sort, присутствующий в родительском элементе, определяет первичный ключ сортировки, второй элемент — вторичный ключ, и так далее.

Как можно видеть, элемент xsl:sort определяет сортировку достаточно гибко, но вместе с тем не следует забывать, что эти возможности могут быть реализованы в процессорах далеко не полностью. Поэтому одна и та же сортировка может быть выполнена в разных процессорах по-разному.

Приведем простой пример сортировки имен и фамилий.

Пример

Листинг 8.10. Входящий документ

<list>
    <person>
        <name>William</name>
        <surname>Gibson</surname>
    </person>
    <person>
        <name>William</name>
        <surname>Blake</surname>
    </person>
    <person>
        <name>John</name>
        <surname>Fowles</surname>
    </person>
</list>

Отсортируем этот список сначала по именам в убывающем, а затем по фамилиям в возрастающем порядке.

<xsl:template match="list">
    <xsl:copy>
        <xsl:for-each select="person">
            <xsl:sort select="name" order="descending"/>
            <xsl:sort select="surname"/>
            <xsl:copy-of select="."/>
        </xsl:for-each>
    </xsl:copy>
</xsl:template>

Листинг 8.12. Выходящий документ

<list>
    <person>
        <name>William</name>
        <surname>Blake</surname>
    </person>
    <person>
        <name>William</name>
        <surname>Gibson</surname>
    </person>
    <person>
        <name>John</name>
        <surname>Fowles</surname>
    </person>
</list>

К сожалению, сортировкой нельзя управлять динамически. Все атрибуты элемента xsl:sort должны обладать фиксированными значениями.

Ссылки

MDN xsl:sort на MDN
MSDN xsl:sort на MSDN