У приведенного здесь способа формирования ключа есть определенные ограничения: необходимо иметь априорную информацию о строковых значениях каждого из свойств, составляющих наш композитный ключ для того, чтобы корректно формировать его строковые представления. Например, если бы в приведенном выше документе имена объектов и источников могли бы содержать символ "
–
", было бы непонятно, к какому объекту относится составной ключ "
a-b-c
":
к объекту с источником
a-b
и именем
с
или к объекту с источником
а
и именем
b-c
. К счастью, в большинстве случаев такая информация имеется, и генерировать составные ключи не очень сложно.
Функция key в паттернах
Разбирая синтаксические правила построения паттернов, мы встретились с особой формой паттерна, в котором могла использоваться функция
key
. Приведем еще раз эту продукцию:
[PT3] IdKeyPattern ::= 'id' '(' Literal ')'
| 'key' '(' Literal ',' Literal ')'
Функция
key(key-name, key-value)
в паттерне будет соответствовать узлам, значение ключа
key-name
которых равняется или принадлежит объекту
key-value
. Это позволяет использовать возможности ключей при проверке узлов на соответствие образцу.
Пример
Предположим, что нам нужно по-особому обработать объекты, принадлежащие источнику
а
. Для этого мы можем создать шаблон следующего вида.
Листинг 8.30. Шаблон, использующий функцию key в паттерне
<xsl:template match="key('src', 'a')">
<!-- Содержимое шаблона -->
</xsl:template>
Этот шаблон будет применяться к любым узлам, имеющим ключ
src
со значением
а
.
Нумерация
Нумерация, несомненно, является одной из самых естественных проблем, решаемых при помощи XSLT. Задача нумерации состоит в том, чтобы, исходя из позиции обрабатываемого узла в дереве документа, вычислить по заданным критериям его порядковый номер. В качестве примера такого рода задачи можно привести вывод номеров частей, разделов и глав книги, указание номеров элементов списка или строк таблицы.
Для вычисления порядковых номеров узлов в дереве в XSLT существует несколько способов. В простых случаях для достижения цели бывает достаточно воспользоваться одним из следующих XPath-выражений.
□ Для того чтобы получить порядковый номер текущего узла в обрабатываемом множестве, можно использовать функцию
position
. Обратим внимание, что это будет позиция узла в обрабатываемом в данный момент множестве, а не в дереве исходящего документа.
□ Функция
count(preceding-sibling::*)+1
возвращает порядковый номер текущего элемента среди других элементов его родителя, иначе говоря, среди его братьев. Путь выборки
preceding-sibling::*
выбирает множество братских элементов, предшествующих текущему узлу, а функция
count
вычисляет их количество. Таким образом, значение
count(preceding-sibling::*)+1
будет равно
1
для первого элемента (поскольку ему другие элементы не предшествуют),
2
— для второго (ему предшествует один элемент) и так далее.