Вызов шаблона во многом похож на вызов функции, что обсуждалось в главе 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
Читать дальше