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

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

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

Работа с параметрами обеспечивается двумя элементами —

xsl:param
, который объявляет в шаблоне новый параметр и
xsl:with-param
, который указывает значение параметра при вызове шаблона.

Элемент xsl:param

Синтаксически этот элемент задается как:

name="имя"

 select="выражение">

Элемент

xsl:template
, задающий в преобразовании шаблонное правило, может включать несколько элементов
xsl:param
, которые и будут определять параметры этого шаблона. Кроме этого,
xsl:param
может указываться в виде элемента верхнего уровня — в этом случае он будет определять глобальный параметр.

Элемент

xsl:param
объявляет параметр с именем, которое задается обязательным атрибутом
name
. Имя параметра может иметь расширенную форму, например
"user:param"
, но чтобы не возиться с пространствами имен, на практике имена всегда дают простые — типа
"i"
или
"myParam"
.

Параметру может быть присвоено значение по умолчанию — то есть значение, которое будет использоваться в случае, если параметра с таким именем шаблону передано не было. Значение по умолчанию вычисляется следующим образом:

□ если в элементе

xsl:param
определен атрибут
select
, то значением по умолчанию будет результат вычисления выражения, указанного в этом атрибуте;

□ если атрибут

select
не определен, но сам элемент
xsl:param
имеет дочерние узлы, то значением определяемого параметра по умолчанию будет фрагмент дерева, полученного в результате выполнения содержимого
xsl:param
;

□ если атрибут

select
не определен и при этом сам элемент
xsl:param
пуст, то значением параметра по умолчанию будет пустая строка.

Примеры

Элемент

создаст параметр, значением которого по умолчанию будет

4
. Точно такой же эффект будет иметь элемент

25
" и тем более не множество, состоящее из текстового узла со значением
25
. Значением параметра
x
по умолчанию будет результирующий фрагмент дерева, корень которого будет иметь единственный текстовый узел со значением "
25
" (рис. 5.3).

Рис. 5.3. Фрагмент дерева, который будет значением параметра x по умолчанию

Не стоит пугаться такой структуры в качестве значения параметра. То, что параметр

x
вдруг будет содержать дерево, ничуть не ограничивает его использование, ведь дерево при потребности может быть приведено к числу или к строке; к множеству узлов же не может быть приведен ни один тип данных.

Предупреждение

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

Определение параметра вида:

то есть когда в нем нет ни атрибута

select
, ни содержимого, присвоит параметру пустую строку, то есть будет эквивалентно

Точно так же, как и в случае с переменными, значение заданного в шаблоне параметра можно использовать в выражениях, добавляя перед именем параметра префикс "

$
". К примеру, значение нашего параметра x может быть получено конструкцией вида
$x
.

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

xsl:with-param
, который мы рассмотрим чуть ниже. Глобальные параметры, объявленные элементами
xsl:param
верхнего уровня, также могут быть переданы преобразованию, однако конкретный механизм реализации этой передачи целиком и полностью зависит от реализации конкретного процессора.

Область видимости параметров

Область видимости параметров определяется в точности так же, как область видимости переменных. Единственным, на что следует обратить здесь внимание — это то, что элементы

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

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

Элемент xsl:with-param

Синтаксис этого элемента выглядит следующим образом:

name="имя"

 select="выражение">

Как можно заметить, элемент

xsl:with-param
абсолютно идентичен элементу
xsl:param
(отличаются только их имена). Практически настолько же похоже и их действие: элемент
xsl:with-param
тоже связывает с именем параметра значение, и при выполнении шаблона это значение будет использоваться вместо значения параметра по умолчанию.

Таким образом, значение параметра, заданного в шаблоне, выбирается в соответствии со следующими положениями:

□ если в элементе, который вызывает этот шаблон, присутствует элемент

xsl:with-param
, передающий значение этого параметра, в шаблоне будет использоваться переданное значение;

□ если в элементе, который вызывает этот шаблон, элемента

xsl:with-param
, с соответствующим именем нет, в качестве значения параметра будет использоваться значение по умолчанию.

Элемент

xsl:with-param
может использоваться только в качестве дочернего элемента
xsl:apply-templates
и
xsl:call-template
.

В качестве простого примера приведем шаблон, который выводит сокращение названия для недели по его номеру. Номер дня передается в шаблон параметром с именем

day-number
.

Листинг 5.26. Вывод названия дня недели по номеру

Mon

Tue

Wed

Thu

Fri

Sat

Sun

Hmm...

Результатом вызова:

будет текстовый узел "

Mon
". Рассмотрим теперь случай, когда параметра передано не было:

Шаблон выведет задумчивое

Hmm...
, поскольку значение параметра
day-number
будет по умолчанию нулем (атрибут
select
имеет вид
select="0"
) и в операторе выбора
xsl:choose
сработает условие
xsl:otherwise
.

Параметры могут быть использованы как в именованных, так и в неименованных шаблонах. Именованные шаблоны с параметрами ведут себя как самые настоящие функции — они могут вызываться с определенными параметрами вне зависимости от контекста, только чтобы выполнить какие-либо действия с переданными значениями. В случае обычных, неименованных шаблонов параметры могут предоставлять некую дополнительную информацию.

Пример

Представим себе описание меню в следующем формате:

Для того чтобы при обработке особым образом выделять текущую страницу, определим в шаблоне параметр

current
и будем выводить название страницы в элементе
b
(от англ. bold — полужирный), если значение
current
равно индексу данного пункта меню; если текущая страница и индекс пункта меню не совпадают, то выводиться будет ссылка.

Результатом выполнения шаблона

будет фрагмент меню вида

Home

News

Profile

Contact

Попробуем теперь обработать элементы

menuitem
, не указывая значение параметра
current
:

Результат будет получен в виде:

Home

<а href="news.htm">News

<а href="profile.htm">Profile

Contact

Этот фрагмент выходящего документа легко объяснить. Вследствие определения:

значением параметра

current
по умолчанию является
1
, и поэтому в меню был выбран пункт с индексом
1
.

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

Итак, предположим, что мы генерируем выходящий документ следующим именованным шаблоном:

Title one

content

Параметр

head
по умолчанию будет содержать дерево, состоящее из элемента
head
и его дочернего элемента
title
, который содержит текст "
Title one
". Результат выполнения вызова

мы можем видеть на следующем листинге:

Title one

content

Выделенный фрагмент относится к части дерева, которая была создана копированием значения параметра

head
.

Попробуем теперь передать в качестве параметра дерево, сгенерированное следующим шаблоном:

Title two

Для того чтобы передать результат выполнения этого шаблона в виде значения параметра

head
именованному шаблону
head
, воспользуемся следующей конструкцией:

Выходящий документ будет получен в виде:

Title two

content

Выделенный фрагмент, как и в предыдущем случае, соответствует части документа, полученной при копировании значения параметра

head
.

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

Глава 6