всей своей простоте и вычислительной мощи, рекурсия является гораздо более требовательной к ресурсам техникой программирования, чем обычная итеративная обработка. Поэтому всегда следует тщательно оценивать, во что может вылиться использование рекурсии. В любом случае следует избегать глубоких рекурсий (функций, количество рекурсивных вызовов в которых может быть большим) и рекурсий, неэкономно использующих память.
Кроме того, большинство действий, выполнение которых в XSLT затруднено, в классических языках программирования выполняется, как правило, намного легче и эффективней. Поэтому, каждый раз, когда стоит вопрос об использовании рекурсии, наряду с ней следует рассматривать такую альтернативу, как использование расширений XSLT, написанных на обычном императивном языке.
Метод Пиза для for-цикла
Для простых for-циклов, которые должны выполниться строго определенное число раз, вместо рекурсии можно использовать весьма остроумный метод, предложенный Венделлом Пизом (Wendell Piez, Mullberry Technologies, Inc). Суть метода состоит в том, что хоть мы и не можем сгенерировать множество узлов, выбрать множество с определенным количеством узлов нам вполне по силам.
Для начала выберем какое-нибудь множество узлов документа преобразования:
<xsl:variable name='set' select='document('')//node()'/>
Затем для повторения определенных действий несколько раз используем конструкцию вида
<xsl:for-each select='$set[position() <= $number]'>
 <!-- Действия -->
</xsl:for-each>
где number указывает требуемое число итераций.
При использовании метода Пиза следует учитывать следующие особенности.
□ Множество узлов set не должно быть слишком большим — иначе его выбор будет неэффективным. 
□ Множество узлов set обязательно должно содержать число итераций (number) узлов.
В целом же метод Пиза — классический пример эффективного применения инструментов не по назначению.
Операции над множествами
Рассматривая такой тип данных, как множества узлов, мы отмечали ограниченность операций, которые можно с ними производить. В частности, XSLT не предоставляет стандартных операторов для определения принадлежности одного множества другому, нахождения пересечений, разности множеств и так далее. Возможности, которые были представлены при описании этого типа данных, основанные на использовании оператора равенства, на самом деле реализуют далеко не математические операции над множествами.
В этом разделе мы рассмотрим иной подход к реализации операций над множествами, основанный на очень простом определении принадлежности узла множеству. Узел node принадлежит множеству nodeset тогда и только тогда, когда выполняется равенство
count($nodeset) = count($node | $nodeset)
Учитывая это обстоятельство, операции над множествами можно представить, как показано в табл. 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.) и публикуются с любезного разрешения авторов.
Перенос строк и элементы
Большинству читателей, скорее всего, хорошо знаком такой элемент языка HTML, как BR, который используется для обозначения разрыва строки. В обычных текстовых файлах для той же самой цели используются символы с кодами #xA, #xD или их комбинации в зависимости от платформы. При совместном использовании неразмеченного текста и HTML часто возникает задача преобразования символов перевода строки в элементы BR и наоборот.
Замену элемента BR на текстовый узел, содержащий перевод строки, можно проиллюстрировать следующим тривиальным шаблоном.
<xsl:template match='BR'>
 <xsl:text>
</xsl:text>
</xsl:template>




