Каковы различия между 'call-template' и 'apply-templates' в XSL? - PullRequest
113 голосов
/ 18 декабря 2010

Я новичок в XSLT, поэтому меня немного смущают два тега:

<xsl:apply-templates name="nodes">

и

<xsl:call-template select="nodes"> 

Так вы можете перечислить разницу между ними?

Ответы [ 4 ]

151 голосов
/ 18 декабря 2010

<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), итерирует их ( это важно: применять -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> не изменяет текущий узел. То есть . в вызываемом шаблоне относится к тому же узлу, что и . в вызывающем шаблоне. Это не относится к apply-шаблонам.

В этом основная разница. Существуют и другие аспекты шаблонов, которые влияют на их поведение: их mode и priority, тот факт, что шаблоны могут иметь как name, так и match. Это также влияет на то, был ли шаблон импортирован (<xsl:import>) или нет. Это расширенные возможности, и вы можете справиться с ними, когда попадете туда.

15 голосов
/ 18 декабря 2010

Чтобы добавить к хорошему ответу @Tomalak:

Вот некоторые не упомянутые и важные отличия :

  1. xsl:apply-templates намного богаче и глубже, чем xsl:call-templates и даже из xsl:for-each, просто потому, что мы не знаем, какой код будет применен к узлам выбора - в общем случае этот код будет отличаться дляразные узлы списка узлов.

  2. Код, который будет применен, может быть написан способом после того, как xsl:apply template s был написан и людьми, которые не знают первоначального автора.

В библиотеке FXSL реализация функций высшего порядка (HOF) в XSLT была бы невозможна , если бы XSLT не имел <xsl:apply-templates> инструкция.

Сводка : Шаблоны и инструкция <xsl:apply-templates> - это то, как XSLT реализует и работает с полиморфизмом.

Ссылка : См. Этовся нить: http://www.biglist.com/lists/lists.mulberrytech.com/xsl-list/archives/200411/msg00546.html

6 голосов
/ 18 декабря 2010

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, чье имя - «узлы».

2 голосов
/ 18 декабря 2010

Функциональность действительно аналогична (кроме семантики вызова, где для call-template требуется атрибут name и соответствующий шаблон имен).

Однако синтаксический анализатор не будет выполняться таким же образом.

С MSDN :

В отличие от <xsl:apply-templates>, <xsl:call-template> не изменяет текущий узел или текущий список узлов.

...