Рекурсия это более распростаненный метод организации цикла со счетчиком в XSLT.
Однако он же и более ресурсоемкий.
Метод Пиза позволяет избавиться от рекурсии и тем самым оптимизировать выполнение шаблона. При этом, надо учитывать, что в реальных задачах можно в качестве содержимого переменной $set использовать не набор узлов обрабатываемого XML-документа, а набор узлов самого шаблона, записав переменную как
, и тогда наш цикл не будет зависеть от обрабатываемого документа.
(В данной, чисто условной задаче, это к сожалению, невозможно, из-за малого числа узлов в XSL-шаблоне цикл доходит только до 36. Но тут можно вспомнить о том, что каждый комментарий в шаблоне тоже считается узлом. Поэтому можно написать комментариев к каждой строке, и добить всеь шаблон пустыми комментариями в конце, чтобы цикл дошел до ста, пример ниже)
Ну и если уж совсем удариться в оптимизацию, то имеет смысл вынести деление в отдельные переменные и оптимизировать первое условие, проверяя в нем сначала делимость на 5 а потом только делимость на 3.
Тогда получится следующее:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="UTF-8"/>
<!--Программа FizzBuzz-->
<xsl:template match="/">
<!--Выберем все узлы текущего документа-->
<xsl:variable name="set" select="document('')//node()"/>
<!--Создадим цикл со счетчиком-->
<xsl:for-each select="$set[position() <= 100]">
<!--Вычислим значение остатка от деления текущего числа на 5-->
<xsl:variable name="mod5" select="position() mod 5"/>
<!--Вычислим значение остатка от деления текущего числа на 3-->
<xsl:variable name="mod3" select="position() mod 3"/>
<!--Проверим выполение условий задачи-->
<xsl:choose>
<!--Если число кратно и пяти и трем то выведем "FizzBuzz"-->
<xsl:when test="$mod5 = 0 and $mod3 = 0">FizzBuzz</xsl:when>
<!--Если число кратно трем то выведем "Buzz"-->
<xsl:when test="$mod3 = 0">Buzz</xsl:when>
<!--Если число кратно пяти то выведем "Fizz"-->
<xsl:when test="$mod5 = 0">Fizz</xsl:when>
<!--Во всех остальных случаях выведем само число-->
<xsl:otherwise>
<xsl:value-of select="position()"/>
</xsl:otherwise>
</xsl:choose>
<!--Выведем пробел-->
<xsl:text> </xsl:text>
</xsl:for-each>
</xsl:template>
<!-- -->
<!-- -->
<!-- -->
<!-- -->
<!-- -->
<!-- -->
<!-- -->
<!-- -->
<!-- -->
<!-- -->
<!-- -->
<!-- -->
<!-- -->
<!-- -->
<!-- -->
<!-- -->
<!-- -->
<!-- -->
<!-- -->
<!-- -->
<!-- -->
</xsl:stylesheet>
Да, это извращение чистой воды, но… на профайлере ваш способ выполняется примерно 0,0184 с, а мой — 0,0104 с. При этом глубина стека в вашем варианте составляет 301, а в моем — 4.
По-моему это профит, однозначно! :)
Ну то есть я понимаю что именно в данной задаче подобная оптимизация не имеет никакого практического смысла, но мои рассуждения вообще-то к тому, что не стоит всегда пользоваться только стандартными походами. В одном из проектов учет подобных нюансов серёзно облегчил жизнь серверу, а в конечном итоге и мне :-)
Отправил ссылочку на календарик своим друзьям, а от них поступило предложение скрестить его вот с этим: www.ii.uib.no/~arntzen/kalender/
Ну чтобы уже полный вынос мозга! :-)
Однако он же и более ресурсоемкий.
Метод Пиза позволяет избавиться от рекурсии и тем самым оптимизировать выполнение шаблона. При этом, надо учитывать, что в реальных задачах можно в качестве содержимого переменной $set использовать не набор узлов обрабатываемого XML-документа, а набор узлов самого шаблона, записав переменную как , и тогда наш цикл не будет зависеть от обрабатываемого документа.
(В данной, чисто условной задаче, это к сожалению, невозможно, из-за малого числа узлов в XSL-шаблоне цикл доходит только до 36. Но тут можно вспомнить о том, что каждый комментарий в шаблоне тоже считается узлом. Поэтому можно написать комментариев к каждой строке, и добить всеь шаблон пустыми комментариями в конце, чтобы цикл дошел до ста, пример ниже)
Ну и если уж совсем удариться в оптимизацию, то имеет смысл вынести деление в отдельные переменные и оптимизировать первое условие, проверяя в нем сначала делимость на 5 а потом только делимость на 3.
Тогда получится следующее:
Да, это извращение чистой воды, но… на профайлере ваш способ выполняется примерно 0,0184 с, а мой — 0,0104 с. При этом глубина стека в вашем варианте составляет 301, а в моем — 4.
По-моему это профит, однозначно! :)
Ну то есть я понимаю что именно в данной задаче подобная оптимизация не имеет никакого практического смысла, но мои рассуждения вообще-то к тому, что не стоит всегда пользоваться только стандартными походами. В одном из проектов учет подобных нюансов серёзно облегчил жизнь серверу, а в конечном итоге и мне :-)
Для краткости кода использован метод Пиза, поэтому число узлов в обрабатываемом xml должно быть не менее ста.
Ну чтобы уже полный вынос мозга! :-)