обрабатываемого документа. Значением выражения, заданного в атрибуте use, будет множество всех узлов атрибутов каждого из элементов
item
. Таким образом, множество узлов будет иметь следующий вид:
(<item name="А".../>, 'src', 'a')
(<item name="А".../>, 'src', 'A')
(<item name="В".../>, 'src', 'b')
(<item name="В".../>, 'src', 'В')
(<item name="С".../>, 'src', 'а')
(<item name="С".../>, 'src', 'С')
(<item name="D".../>, 'src', 'с')
(<item name="D".../>, 'src', 'D')
...
(<item name="H".../>, 'src', 'a')
(<item name="H".../>, 'src', 'H')
В итоге функция
key('src', 'a')
будет возвращать объекты с именами
A
,
C
и
H
, а функция
key('src', 'A')
— единственный объект с именем
A
(поскольку ни у какого другого элемента
item
нет атрибута со значением
"A"
).
Необходимо сделать следующее замечание: совершенно необязательно, чтобы процессор действительно физически создавал в памяти множества ключей. Это множество определяется чисто логически — чтобы было ясно, что же все-таки будет возвращать функция
key
. Процессоры могут вычислять значения ключей и искать узлы в документе и во время выполнения, не генерируя ничего заранее. Но большинство процессоров, как правило, все же создают в памяти определенные структуры для манипуляций с ключами. Это могут быть хэш-таблицы, списки, простые массивы или более сложные нелинейные структуры, упрощающие поиск, — важно другое. Важно то, что имея явное определение ключа в
xsl:key
, процессор может производить такую оптимизацию.
Использование нескольких ключей в одном преобразовании
В случае, когда к узлам в преобразовании нужно обращаться по значениям различных свойств, можно определить несколько ключей — каждый со своим именем. Например, если мы хотим в одном случае обращаться к объектам, принадлежащим одному источнику, а во втором — к объектам с определенными именами, мы можем определить в документе
два ключа — один с именем
src
, второй — с именем
name
:
<xsl:key name="src" match="item" use="@source"/>
<xsl:key name="name" match="item" use="@name"/>
Множество ключей, созданных этими двумя определениями, будет выглядеть следующим образом:
(<item name="А".../>, 'src', 'а')
(<item name="А".../>, 'name', 'А')
(<item name="В".../>, 'src', 'b')
(<item name="В".../>, 'name', 'В')
(<item name="C".../>, 'src', 'a')
(<item name="C".../>, 'name', 'С')
(<item name="D".../>, 'src', 'с')
(<item name="D".../>, 'name', 'D')
...
(<item name="H".../>, 'src', 'a')
(<item name="H".../>, 'name', 'H')
В этом случае функция
key('src', 'а')
возвратит объекты с именами
A
,
C
и
H
, а функция
key('name', 'а')
— объект с именем
А
.
Имя ключа является расширенным именем. Оно может иметь объявленный префикс пространства имен, например
<xsl:key
name="data:src"
match="item"
use="@source"
xmlns:data="urn:user-data"/>
В этом случае функция
key(key-name, key-value)
будет возвращать узлы, значение ключа с расширенным именем
key-name
которых равно
key-value
. Совпадение расширенных имен определяется как обычно — по совпадению локальных частей и URI пространств имен.
Использование нескольких определений одного ключа
Процессор должен учитывать все определения ключей данного преобразования — даже если некоторые из них находятся во включенных или импортированных модулях. Порядок импорта элементов
xsl:key
не имеет значения: дело в том, что определения ключей с одинаковыми именами для одних и тех же узлов, но с разными значениями ключа не переопределяют, а дополняют друг друга.
Пример
Предположим, что в нашем документе имеется несколько элементов
item
, в которых не указано значение атрибута
source
, но по умолчанию мы будем причислять их к источнику
а
. Соответствующие ключи будут определяться следующим образом: