Технология XSLT — страница 56 из 66

Рассматривая такой тип данных, как множества узлов, мы отмечали ограниченность операций, которые можно с ними производить. В частности, XSLT не предоставляет стандартных операторов для определения принадлежности одного множества другому, нахождения пересечений, разности множеств и так далее. Возможности, которые были представлены при описании этого типа данных, основанные на использовании оператора равенства, на самом деле реализуют далеко не математические операции над множествами.

В этом разделе мы рассмотрим иной подход к реализации операций над множествами, основанный на очень простом определении принадлежности узла множеству. Узел

node
принадлежит множеству
nodeset
тогда и только тогда, когда выполняется равенство

count($nodeset) = count($node | $nodeset)

Учитывая это обстоятельство, операции над множествами можно представить, как показано в табл. 11.1. Результирующее множество выделено штриховкой.


Таблица 11.1. Операции над множествами

ОперацияГрафическое представлениеXPath-выражение
Объединение
$A | $B
Пересечение
$А[count(.|$B)=count($B)]
Разность
$A[count(.|$B)!=count($B)]
Симметрическая разность
$A[count(.|$B)!=count($B)] | $B[count(.|$A)!=count($A)]

Приведенные выше методы были разработаны Майклом Кеем (Michael Kay, Software AG), Оливером Беккером (Oliver Becker, Humboldt-Universitat zu Berlin), Кеном Холманом (Ken Holman, Crane Softwrights Ltd.) и публикуются с любезного разрешения авторов.

Перенос строк и элементы BR

Большинству читателей, скорее всего, хорошо знаком такой элемент языка HTML, как

BR
, который используется для обозначения разрыва строки. В обычных текстовых файлах для той же самой цели используются символы с кодами
#xA
,
#xD
или их комбинации в зависимости от платформы. При совместном использовании неразмеченного текста и HTML часто возникает задача преобразования символов перевода строки в элементы
BR
и наоборот.

Замену элемента

BR
на текстовый узел, содержащий перевод строки, можно проиллюстрировать следующим тривиальным шаблоном.

Листинг 11.16. Шаблон замены элементов BR на перенос строки


Гораздо сложнее написать шаблон, делающий обратную операцию, — замену символов переноса строки на элементы BR. В XSLT нет встроенного механизма для замены подстроки в строке (тем более на элемент), поэтому нам придется создать для этой цели собственный шаблон.

Для этой цели мы можем воспользоваться функциями

substring-before
и
substring-after
. Функция
substring-before($str, $search-for)
возвратит часть строки
str
, которая предшествует первому вхождению в нее подстроки
search-for
, а функция
substring-after($str, $search-for)
— последующую часть. То есть заменить первое вхождение можно шаблоном вида

Для того же, чтобы заменить все вхождения, достаточно рекурсивно повторить операцию замены первого вхождения с той частью строки, которая следует за ним. Приведем шаблон, который выполняет эту операцию.

Листинг 11.17. Шаблон для замены подстроки в строке


     select="substring-after($str, $search-for)"/>

Шаблон, приведенный в этом листинге, может быть вызван двумя способами: элементом

xsl:apply-templates
в режиме
replace
(в этом случае он будет обрабатывать текстовые узлы выбранного множества), или при помощи именного вызова элементом
xsl:call-template
. Шаблон принимает на вход три параметра.

□ Параметр

str
, содержащий строку, в которой нужно произвести замену. По умолчанию этому параметру присваивается текстовое значение текущего узла.

□ Параметр

search-for
, содержащий подстроку, которую требуется найти и заменить в строке
str
. По умолчанию замене будут подлежать символы переноса строки, "
&#хА;
".

□ Параметр

replace-with
, содержащий объект, на который следует заменять подстроки
search-for
. По умолчанию эти подстроки будут заменяться на элемент
BR
и следующий за ним перенос строки, добавленный для лучшей читаемости.

В качестве примера отформатируем содержание следующего элемента:

One little rabbit

Two little rabbits

Three little rabbits