Чтение онлайн

ЖАНРЫ

Технология XSLT

Валиков Алексей Н.

Шрифт:

□ для каждого из найденных узлов (

x
X
) вычислить значение выражения атрибута
use
(значение
u(x)
);

□ если

u(x)
является множеством узлов (назовем его
Uх
), то для каждого
uxi
Uх
создать ключ
(x, n, string(uxi))
, где
n
— имя ключа (значение атрибута
name
элемента
xsl:key
);

если
u(x)
является объектом другого типа (назовем его
ux
), создать ключ
(x, n, string(ux))
.

Пример

Найдем множество ключей, создаваемое определением

<xsl:key name="src" match="item" use="@*"/>

Имена всех ключей будут одинаковы и равны

"src"
. Множество
x
узлов, удовлетворяющих паттерну
item
, будет содержать все элементы
item
обрабатываемого документа. Значением выражения, заданного в атрибуте 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
, но по умолчанию мы будем причислять их к источнику
а
. Соответствующие ключи будут определяться следующим образом:

<xsl:key name="src" match="item[@source]" use="@source"/>

<xsl:key name="src" match="item[not(@source)]" use="'a'"/>

To есть для тех элементов

item
, у которых есть атрибут
source
, значением ключа будет значение этого атрибута, для тех же элементов, у которых атрибута
source
нет, его значением будет
"а"
.

Для входящего документа вида

<items>

 <item source="a" name="A"/>

Поделиться с друзьями: