Ответы:
<xsl:call-template>
является близким эквивалентом вызова функции на традиционном языке программирования.
Вы можете определять функции в XSLT, например эту простую, которая выводит строку.
<xsl:template name="dosomething">
<xsl:text>A function that does something</xsl:text>
</xsl:template>
Эту функцию можно вызвать через <xsl:call-template name="dosomething">
.
<xsl:apply-templates>
немного отличается, и в этом заключается реальная сила XSLT: он принимает любое количество узлов XML (независимо от того, что вы определяете в select
атрибуте), выполняет их итерацию ( это важно: apply-templates работает как цикл! ) и находит подходящие шаблоны для них:
<!-- sample XML snippet -->
<xml>
<foo /><bar /><baz />
</xml>
<!-- sample XSLT snippet -->
<xsl:template match="xml">
<xsl:apply-templates select="*" /> <!-- three nodes selected here -->
</xsl:template>
<xsl:template match="foo"> <!-- will be called once -->
<xsl:text>foo element encountered</xsl:text>
</xsl:template>
<xsl:template match="*"> <!-- will be called twice -->
<xsl:text>other element countered</xsl:text>
</xsl:template>
Таким образом, вы уступаете XSLT-процессору небольшой контроль - не вы решаете, куда пойдет поток программы, но процессор решает, находя наиболее подходящее соответствие для узла, который он обрабатывает в настоящее время.
Если несколько шаблонов могут соответствовать узлу, выигрывает тот, у которого более конкретное выражение соответствия. Если существует более одного совпадающего шаблона с одинаковой специфичностью, побеждает тот, который был объявлен последним.
Вы можете больше сконцентрироваться на разработке шаблонов и меньше времени уделять «сантехнике». Ваши программы станут более мощными и модульными, менее глубоко вложенными и более быстрыми (поскольку процессоры XSLT оптимизированы для сопоставления шаблонов).
С XSLT следует понимать концепцию «текущего узла». С <xsl:apply-templates>
текущим узлом переходит к каждой итерации, <xsl:call-template>
при этом текущий узел не изменяется. Т.е. .
внутри вызываемого шаблона относится к тому же узлу, что и .
в вызывающем шаблоне. Это не относится к шаблонам приложений.
Это основная разница. Есть и другие аспекты шаблонов, которые влияют на их поведение: их mode
и priority
, тот факт, что шаблоны могут иметь как a, так name
и match
. Это также влияет на то, был ли шаблон импортирован ( <xsl:import>
) или нет. Это сложные варианты использования, и вы сможете с ними справиться, когда доберетесь до них.
<xsl:apply-templates>
ведет себя как цикл. Различия в реализации на стороне XSLT-процессора не повлияют на меня как на XSLT-программиста, результат абсолютно одинаков как для параллельных, так и для итеративных реализаций. Но для новичка в XSLT с императивным фоном это помогает представить себе <xsl:apply-templates>
как бы своего рода цикл для каждого, даже если - технически - это не так.
Чтобы добавить к хорошему ответу @Tomalak:
Вот некоторые не упомянутые и важные отличия :
xsl:apply-templates
намного богаче и глубже, чем xsl:call-templates
и даже от xsl:for-each
, просто потому , что мы не знаем, какой код будет применен к узлам выборки - в общем случае этот код будет отличаться для разных узлов списка узлов.
Код, который будет применяться, может быть написан после того, как xsl:apply template
был написан s, и людьми, которые не знают первоначального автора.
Библиотека FXSL «s реализация функций высшего порядка (Хоф) в XSLT не было бы возможно , если XSLT не было <xsl:apply-templates>
инструкции.
Резюме : Шаблоны и <xsl:apply-templates>
инструкции - это то, как XSLT реализует полиморфизм и работает с ним.
Ссылка : См. Всю эту ветку: http://www.biglist.com/lists/lists.mulberrytech.com/xsl-list/archives/200411/msg00546.html
xsl:apply-templates
обычно (но не обязательно) используется для обработки всех или подмножества дочерних элементов текущего узла со всеми применимыми шаблонами. Это поддерживает рекурсивность приложения XSLT, которая соответствует (возможной) рекурсивности обрабатываемого XML.
xsl:call-template
с другой стороны, это больше похоже на обычный вызов функции. Вы выполняете ровно один (именованный) шаблон, обычно с одним или несколькими параметрами.
Поэтому я использую, xsl:apply-templates
если хочу перехватить обработку интересного узла и (обычно) что-то ввести в выходной поток. Типичный (упрощенный) пример:
<xsl:template match="foo">
<bar>
<xsl:apply-templates/>
</bar>
</xsl:template>
тогда как с xsl:call-template
я обычно решаю такие проблемы, как добавление текста некоторых подузлов вместе, преобразование выбранных наборов узлов в текст или другие наборы узлов и т.п. - все, для чего вы бы написали специализированную функцию многократного использования.
В качестве дополнительного примечания к тексту вашего конкретного вопроса:
<xsl:call-template name="nodes"/>
Это вызывает шаблон с именем «узлы»:
<xsl:template name="nodes">...</xsl:template>
Это другая семантика, чем:
<xsl:apply-templates select="nodes"/>
... который применяет все шаблоны ко всем дочерним элементам вашего текущего узла XML, имя которого - «узлы».
Функциональность действительно похожа (кроме семантики вызова, где call-template
требуется name
атрибут и соответствующий шаблон имен).
Однако парсер не будет работать таким же образом.
Из MSDN :
В отличие от
<xsl:apply-templates>
,<xsl:call-template>
не изменяет текущий узел или текущий список узлов.
<xsl:apply-templates>
должна быть реализована как цикл - наоборот, он может быть реализован параллельно, потому что разные приложения на разных узлах списка узлов абсолютно независимы друг от друга.