All streams
Search
Write a publication
Pull to refresh
-1
0
Евгений Стриго (Котов) @jameskotov

User

Send message
Рекурсия это более распростаненный метод организации цикла со счетчиком в XSLT.
Однако он же и более ресурсоемкий.

Метод Пиза позволяет избавиться от рекурсии и тем самым оптимизировать выполнение шаблона. При этом, надо учитывать, что в реальных задачах можно в качестве содержимого переменной $set использовать не набор узлов обрабатываемого XML-документа, а набор узлов самого шаблона, записав переменную как
<xsl:variable name="set" select="document('')//node()"/>
, и тогда наш цикл не будет зависеть от обрабатываемого документа.
(В данной, чисто условной задаче, это к сожалению, невозможно, из-за малого числа узлов в 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.
По-моему это профит, однозначно! :)

Ну то есть я понимаю что именно в данной задаче подобная оптимизация не имеет никакого практического смысла, но мои рассуждения вообще-то к тому, что не стоит всегда пользоваться только стандартными походами. В одном из проектов учет подобных нюансов серёзно облегчил жизнь серверу, а в конечном итоге и мне :-)
Вот XSLT здесь еще не было :) Поэтому вот он:
<?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"/>

	<xsl:template match="/">
		<xsl:variable name="set" select="//node()"/>

		<xsl:for-each select="$set[position() <= 100]">
			<xsl:choose>
				<xsl:when test="position() mod 3 = 0 and position() mod 5 = 0">FizzBuzz</xsl:when>
				<xsl:when test="position() mod 5 = 0">Buzz</xsl:when>
				<xsl:when test="position() mod 3 = 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>

Для краткости кода использован метод Пиза, поэтому число узлов в обрабатываемом xml должно быть не менее ста.
Отправил ссылочку на календарик своим друзьям, а от них поступило предложение скрестить его вот с этим: www.ii.uib.no/~arntzen/kalender/
Ну чтобы уже полный вынос мозга! :-)
2

Information

Rating
Does not participate
Location
Санкт-Петербург, Санкт-Петербург и область, Россия
Date of birth
Registered
Activity