Ваш первый шаблон соответствует узлу numbers
, но ничего не делает.
Ваш второй шаблон ничего не соответствует и никогда не вызывается никаким другим шаблоном.Другими словами, он никогда не выполняется.
Поэтому вывод равен 5.
Посмотрим, что произойдет.В XSLT шаблоны можно вызывать двумя способами.
- Во-первых, они могут соответствовать элементу входных данных XML.Ваш первый шаблон делает именно это: в вашем исходном вопросе он соответствует
/numbers
node;в вашей ревизии он соответствует любому корневому элементу (что в данном случае одно и то же). - Во-вторых, их можно вызывать из шаблона через
call-template
.Это то, что вы делаете во втором шаблоне, рекурсивно вызывая себя.
Проблема в том, что второй шаблон вызывается только из ... угадайте ... самого второго шаблона.Поэтому, поскольку он никогда не вызывается, он никогда не будет выполнен.
Теперь мы добавим вызов к этому шаблону извне, а точнее из первого шаблона.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="numbers">
<output>
<!-- Here's a missing call to the second template -->
<xsl:call-template name="factorial">
<xsl:with-param name="number" select="number"/>
<xsl:with-param name="result" select="1"/>
</xsl:call-template>
</output>
</xsl:template>
<xsl:template name="factorial">
<xsl:param name="number" />
<xsl:param name="result" />
<intermediary number="{$number}">
<xsl:value-of select="$result"/>
</intermediary>
<xsl:if test="$number > 1">
<xsl:call-template name="factorial">
<xsl:with-param name="number" select="$number - 1"/>
<xsl:with-param name="result" select="$number * $result"/>
</xsl:call-template>
</xsl:if>
<xsl:if test="$number = 1">
<result>
<xsl:value-of select="$result"/>
</result>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
Мы такжеМы хотим быть уверены, что шаблон работает правильно, поэтому мы выводим промежуточные состояния.
<?xml version="1.0" encoding="utf-8"?>
<output>
<intermediary number="
 5
 ">1</intermediary>
<intermediary number="4">5</intermediary>
<intermediary number="3">20</intermediary>
<intermediary number="2">60</intermediary>
<intermediary number="1">120</intermediary>
<result>120</result>
</output>
Окончательный результат верен, но первое промежуточное состояние все еще странно.Он показывает, что число 5
обрабатывалось как строка с пробелом в начале и в конце.
Чтобы избавиться от этого, элемент innerXML number
должен быть преобразован в действительное число.Для этого вы можете использовать метод number()
:
<xsl:call-template name="factorial">
<xsl:with-param name="number" select="number(number)"/>
<xsl:with-param name="result" select="1"/>
</xsl:call-template>
Теперь вывод корректен от начала до конца, а промежуточный вывод можно удалить.