</xsl:choose>

</xsl:template>

Вызвав этот шаблон с параметром n равным 6 следующим образом:

<xsl:call-template name='factorial'>

 <xsl:with-param name='n' select='number(6)'/>

</xsl:call-template>

мы получим текстовый узел, значение которого будет равно '720'.

Очевидным требованием к рекурсивным функциям является возможность выхода из рекурсии. Если бы в определении факториала не было указано, что 0!=1, вычисления так бы и продолжались без конца.

Главным минусом рекурсии является требовательность к ресурсам. Каждый раз, при вызове именованного шаблона, процессор должен будет каким-то образом сохранять в памяти передаваемые ему формальные параметры. Например, если мы попробуем сосчитать факториал от 170, процессору понадобится держать в памяти сразу 170 чисел. Безусловно, в случае с факториалом это не является большой проблемой — точность 64-битных чисел исчерпается гораздо раньше, чем закончится память, но в случае хранения в переменных действительно больших объемов информации (например, частей деревьев) такая угроза существует. Кроме того, рекурсивные решения, как правило, работают медленнее, чем решения, не использующие рекурсию.

Так в чем же смысл использования рекурсии? Дело в том, что вследствие определенных ограничений (связанных, в частности с неизменяемыми переменными) в XSLT существуют задачи, которые не могут быть реализованы иначе кроме как через рекурсию. Самым характерным примером такой задачи являются циклы.

Циклы

Цикл в общем смысле слова это повторение одних и тех же действий несколько раз. Если говорить об XSLT, то цикл это многократное выполнение одного и того же шаблона. Для подавляющего большинства случаев в преобразованиях достаточно бывает использовать такие элементы, как xsl:apply- templates и xsl:for-each, которые заставляют процессор выполнять одни и те же действия несколько раз в контексте каждого из узлов определенного множества.

Весомым ограничением такого рода циклической обработки является невозможность генерировать множества узлов. В текущей версии языка никакой другой тип не может быть приведен ко множеству узлов, значит, в любое из них могут входить только те узлы, которые изначально присутствуют в одном из обрабатываемых документов. Это означает, что ни xsl:apply-templates, ни xsl:for- each не могут быть использованы для того, чтобы реализовать простые while- или for-циклы для произвольных множеств.

Цикл while

Наиболее примитивной циклической конструкцией во многих языках программирования является цикл while (англ. пока). Цикл while, как правило, имеет следующий вид:

пока

 верно условие

выполнять

 действия

В качестве примера while-цикла напишем на языке Java программу вычисления факториала в итеративном стиле:

int factorial(int n) {

 int i = n;

 int result = 1;

 while (i != 0) {

  result = result * i;

  i--;

 }

 return result;

}

В этой функции условием является отличие значения переменной i от 0, а действиями — умножение значения переменной result на значение переменной i, и уменьшение значения этой переменной на 1.

Цикл while не может быть запрограммирован в XSLT итеративно потому как действия, как правило, изменяют значения переменных, в контексте которых вычисляется условие, определяющее, продолжать выполнение цикла или нет. Дадим другую общую запись цикла while, выделив изменение переменных:

пока

 верно условие(x1,x2, ...,xn)

выполнить

 x1' := функция1 (x1,x2,...,xn)

 х2' := функция2 (x1,x2,...,xn)

 ...

 xn' := функцияn (x1,x2,...,xn)

 действия(x1,x2,...,хn)

 x1 := x1'

 x2 := x2'

 ...

 xn := xn'

иначе

 вернуть результат(x1,...,хn)

Переопределение значений переменных x1, … , хn в этом случае выполняют n функций: функция1 …, функцияn. И если изменить значение переменной мы не могли, переопределить связанное с ней значение мы вполне в состоянии, добавив в контекст новый параметр или переменную с тем же именем.

Теперь мы можем записать весь цикл while как одну рекурсию:

while(x1, ..., xn) ::=

 если

  выполняется условие(x1, ..., xn)

Вы читаете Технология XSLT
Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату