Чтобы пояснить это, вернемся к нашему примеру: мы ищем элементы
item
со значением атрибута
source
, равным заданному. Свойством, идентифицирующим эти элементы, в данном случае будут значения их атрибутов
source
, которые мы можем заранее вычислить и включить в табл. 8.2.
Таблица 8.2. Значения атрибута
source
элементов
item
Идентификатор (значение атрибута
source
)
Элемент
item
a
<item source="a" name="A"/>
a
<item source="a" name="C"/>
a
<item source="a" name="H"/>
b
<item source="b" name="B"/>
b
<item source="b" name="E"/>
b
<item source="b" name="F"/>
с
<item source="c" name="D"/>
с
<item source="c" name="G"/>
Таким
образом, значение
"с"
идентифицирует объекты с именами
D
и
G
, а значение
"а"
— объекты с именами
A
,
C
и
H
, причем находить соответствующие элементы в таблице по их ключевому свойству не составляет никакого труда.
Несмотря на то, что произведенные нами манипуляции чрезвычайно просты (и настолько же эффективны), процессор вряд ли в общем случае сможет сделать что-либо подобное сам, и потому очень важной является возможность явным образом выделять в XSLT-преобразованиях ключевые свойства множеств узлов.
В этом разделе мы будем рассматривать две конструкции, позволяющие манипулировать множествами узлов посредством ключей — это элемент
xsl:key
, который определяет в преобразовании именованный ключ, и функция
key
, которая возвращает множество узлов, идентифицирующихся заданными значениями ключей.
Элемент xsl:key
Синтаксис элемента несложен:
<xsl:key
name="имя"
match="паттерн"
use="выражение"/>
Элемент верхнего уровня
xsl:key
определяет в преобразовании ключ именем, заданным в значении атрибута
name
, значением которого для каждого узла документа, соответствующего паттерну
match
, будет результат вычисления выражения, заданного в атрибуте
use
. Ни атрибут
use
, ни атрибут
match
не могут содержать переменных.
Пример
В нашем примере элементы
item
идентифицируются значениями своих атрибутов
source
. Для их идентификации мы можем определить ключ с именем
src
следующим образом:
<xsl:key name="src" match="item" use="@source"/>
Следуя строгому определению, данному в спецификации языка, ключом называется тройка вида
(node, name, value)
, где
node
— узел,
name
— имя и
value
— строковое значение ключа. Тогда элементы
xsl:key
, включенные в преобразование, определяют множество всевозможных ключей обрабатываемого документа. Если этому множеству принадлежит ключ, состоящий из узла
x
, имени
у
и значения
z
, говорят, что узел
x
имеет ключ с именем
у
и значением
z
или что ключ
у
узла
x
равен
z
.
Пример
Ключ
src
из предыдущего примера определяет множество, которое состоит из следующих троек:
(<item name="A".../>, 'src', 'a')
(<item name="B".../>, 'src', 'b')
(<item name="C".../>, 'src', 'a')
(<item name="D".../>, 'src', 'c')
...
(<item name="H".../>, 'src', 'a')
В соответствии с нашими определениями мы можем сказать, что элемент
<item source="b" name="B"/>
имеет ключ с именем
"src"
и значением
"b"
или что ключ
"src"
элемента
<item source="a" name="H"/>
равен
"a"
.
Для того чтобы обращаться к множествам узлов по значениям их ключей, в XSLT существует функция
key
, о которой мы сейчас и поговорим.
Функция key
Ниже приведена синтаксическая конструкция данной функции:
node-set key(string, object)
Итак, элементы
xsl:key
нашего преобразования определили множество троек
(node, name, value)
. Функция
key(key-name, key-value)
выбирает все узлы x такие, что значение их ключа с именем
key-name
(первым аргументом функции) равно
key-value
(второму аргументу функции).
Пример
Значением выражения
key('src', 'a')
будет множество элементов
item
таких, что значение их ключа
"src"
будет равно
"а"
. Попросту говоря, это будет множество объектов источника
"а"
.
Концепция ключей довольно проста, и существует великое множество аналогий в других языках программирования: от хэш-функций до ключей в реляционных таблицах баз данных. По всей вероятности, читателю уже встречалось что-либо подобное.