XSLT — страница 76 из 124

шаблоны при помощи параметров.

Элементы и : создание параметров

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

, обладающим двумя атрибутами:

• 

name
(обязательный). Имя переменной, устанавливается в QName;

• 

select
(необязательный). Значение параметра по умолчанию. Устанавливается в выражение XPath.

Аналогично

, этот элемент может либо быть элементом высокого уровня, либо применяться внутри тела шаблона. Параметры, созданные элементами
, являются глобальными, а созданные внутри шаблонов — локальными. При создании параметра внутри тела шаблона, элемент
должен быть расположен перед какими-либо другими дочерними элементами. Элемент может также содержать необязательное тело шаблона, создающее фрагмент результирующего дерева — в XSLT 1.1 это уже не разрешено. Если элемент содержит тело, атрибут
select
использовать нельзя.

После объявления параметра при помощи

к его значению можно обращаться в шаблоне таким же способом, как и к значению переменной, — добавляя к имени префикс «$».

Когда вы вызываете именованный шаблон при помощи

или применяете шаблоны с использованием
, вы можете задать значение используемых в шаблоне параметров с помощью элемента
. Если самому параметру при объявлении было присвоено значение атрибутом
select
элемента
, это значение выступает в качестве значения параметра по умолчанию. Значение по умолчанию будет перекрыто, если вы зададите новое значение параметра при помощи элемента
. У элемента
два атрибута:

• 

name
(обязательный). Имя переменной; устанавливается в QName;

• 

select
(необязательный). Выражение XPath, задающее значение параметра. Если опустить этот атрибут, значение переменной будет определяться содержимым
.

Элемент может также содержать необязательное тело шаблона, создающее фрагмент результирующего дерева, но в XSLT 1.1 это уже не разрешено.

В следующем примере (листинг 9.3) я создаю именованный шаблон с именем «COLORS» (цвета), добавляющий цвет в данные планет в результирующем HTML-документе. Этот именованный шаблон использует единственный параметр,

COLOR
, который устанавливается в требуемый цвет. В примере я устанавливаю параметр
COLOR
в разные цвета для разных планет, используя
и вызывая шаблон «COLORS». Вот как это реализуется на практике.

Листинг 9.3. Применение параметров таблиц стилей

 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  .

  .

  .


 .

 .

 .

Данная таблица вызывает шаблон «COLORS» с разными значениями параметра COLOR. Я могу воспользоваться этими цветами при форматировании данных планет. Заметьте, что я объявил параметр COLOR при помощи

в самом начале шаблона «COLORS»:

 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

   .

   .

   .




 .

 .

 .

И вот результат:

</code></pre></p><p><pre><code>   The Colorful Planets Table</code></pre></p><p><pre><code>

   The Colorful Planets Table

NameMassRadiusDay
Mercury.0553 (Earth = 1)1516 miles58.65 days
Venus.815 (Earth = 1)3716 miles116.75 days
Earth1 (Earth = 1)2107 miles1 days

Этот результирующий документ показан на рис. 9.2 (пусть даже в черно-белом исполнении).

Рис. 9.2. Вызов именованного шаблона с параметрами


В следующем примере я использую параметры для локализации используемого в шаблоне языка. Я создаю новый шаблон

localize
с параметром
language
. Если language установлен в «
en
», означая английский, результирующий документ будет озаглавлен «Planets»; если
language
установлен в «
de
», немецкий, результирующий документ будет озаглавлен «Planeten», а если в «
fr
», французский, результирующий документ будет озаглавлен «Planetes».

Здесь я вызываю шаблон

localize
, установив
language
в «fr»:

 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

</code></pre></p><p><pre><code><b><xsl:call-template name="localize"></b></code></pre></p><p><pre><code><b><xsl:with-param name="language" select="'fr'"/></b></code></pre></p><p><pre><code><b></xsl:call-template></b></code></pre></p><p><pre><code>

     .

     .

     .

А вот как выглядит параметризованный шаблон «COLORS». Заметьте, что я объявляю параметр

COLOR
в шаблоне при помощи элемента
(и заметьте, что в HTML 4.01 символьный элемент для «е» в «Planetes», который я и использую — это
è
):

 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

</code></pre></p><p><pre><code><xsl:call-template name="localize"></code></pre></p><p><pre><code><xsl:with-param name="language" select="'fr'"/></code></pre></p><p><pre><code></xsl:call-template></code></pre></p><p><pre><code>

NameMassRadiusDay


Planets

Planeten

Planètes

 .

 .

 .

Вот результирующий локализованный документ:

Planètes

Planètes

   .

   .

   .

Этот документ показан на рис. 9.3.

Рис. 9.3. Вызов именованного шаблона с параметрами для установки языков


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

Рекурсивный вызов шаблонов

Эта тема предназначена, главным образом, для программистов, поскольку здесь я буду пользоваться XSLT как языком программирования. В частности, я реализую вызов именованным шаблоном самого себя, то есть рекурсивный вызов. Классический пример рекурсии — вычисление факториала: например, факториал 6, что записывается как

6!
, равен
6*5*4*3*2*1
, или
720
.

При реализации рекурсии в настоящем языке программирования создается функция — например,

factorial
, которая вызывается со значением 6:
factorial(6)
. Факториал 6 вычисляется как
6 * factorial(5)
, поэтому функции нужно лишь умножить на 6 результат вызова самой себя со значением 5, то есть
factorial(5)

Далее,

factorial(5)
— это
5*factorial(4)
, поэтому функция снова вызывает сама себя, чтобы вычислить значение
factorial(4)
. Этот процесс продолжается до вычисления
factorial(1)
, а мы знаем, что 1! — это просто 1, поэтому
factorial(1)
возвращает 1. С этого момента управление последовательно возвращается на все предыдущие этапы, в результате чего будет вычислено выражение
1*2*3*4*5*6
, или
720
, что составляет
6!
.

Кажется, что в таком языке стилей, как XSLT, реализовать подобное невозможно. Тем не менее, это можно сделать, по крайней мере, в XSLT 1.0. Основная идея состоит в том, что значение, возвращаемое шаблоном, можно сохранять в переменной, если шаблон вызывается внутри элемента

, в котором объявляется эта переменная. Пусть, например, у нас есть именованный шаблон
factorial
, и мы хотим вычислить
6!
. Тогда шаблону можно передать значение 6 при помощи элемента
и присвоить строковое значение результата переменной
result
, которое я затем показываю:

 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  6! = 

 .

 .

 .

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

factorial
, чтобы для вычисления факториала он вызывал сам себя. На языке программирования я мог бы написать рекурсивный вызов как
n!=n*factorial(n-1)
, но у нас нет оператора присваивания; поэтому, когда я вычисляю
factorial(n-1)
, я сохраняю это значение в новой переменной
temp
и на каждом шаге возвращаю значение
n*$temp
:

 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  6! = 


Вот результирующий документ:

6! = 720

Как видите, это можно сделать, по крайней мере, в XSLT 1.0, в котором разрешены использованные здесь фрагменты результирующего дерева.

Шаблон: значение по умолчанию

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

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

Следующий пример видоизменяет рассмотренный ранее пример «COLORS». Шаблон имеет параметр

COLOR
, но я могу вызвать шаблон, не устанавливая
COLOR
в какое-либо определенное значение:

В этом случае параметр

COLOR
принимает значение по умолчанию«
blue
» (голубой), заданное в элементе
в шаблоне «COLORS»:


Как задавать значения шаблона в командной строке

Кроме возможностей, предоставляемых элементами

и
, значение параметров таблицы стилей во многих процессорах XSLT можно также задавать в командной строке. Способ зависит от конкретного процессора.

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

param1
значение
value1
в командной строке, используя процессор XSLT от Oracle в Windows. Заметьте, что при установке значений параметра в командной строке его все равно нужно объявлять в таблице стилей при помощи
:

C:\>java oraclе.xml.parser.v2.oraxsl -p param1='value1' planets.xml planets.xsl output.xml

Вот как то же самое можно сделать при помощи Saxon:

C:\>saxon source.xml stylesheet.xsl param1=value1 > output.xml

при помощи Xalan:

C:\>java org.apache.xalan.xslt.Process -IN planets.xml -XSL planets.xsl -OUT output.xml -PARAM parma1 value1

и XT:

C:\XSL>java -Dcom jclark.xsl.sax parser=org.apache.xerces.parsers.SAXParser.com.jclark.xsl.sax.Driver planets.xml planets.xsl output.xml param1=value1

Элемент

NameMassRadiusDay