Які відмінності між "шаблоном виклику" та "шаблонами застосування" в XSL?


119

Я новачок у XSLT, тому мене трохи не бентежить щодо двох тегів,

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

і

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

Тож чи можете ви перерахувати різницю між ними?

Відповіді:


167

<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і a match. Це також впливає на те, чи імпортували шаблон ( <xsl:import>) чи ні. Це розширені можливості використання, і ви можете боротися з ними, коли потрапите.


5
@Tomalak: Гарна відповідь! Однак вислів: "xsl: apply-templates is loop" не є правильним. У жодній офіційній специфікації W3C немає вказівки, яка <xsl:apply-templates>повинна бути реалізована як цикл - навпаки, вона може бути реалізована паралельно, тому що різні програми на різних вузлах списку вузлів абсолютно незалежні один від одного.
Димитрій Новатчев

8
@Dimitre: Що я хотів сказати: з точки зору кінцевого користувача, він <xsl:apply-templates>поводиться як цикл. Різниці в реалізації на кінці процесора XSLT не вплинуть на мене як на програміста XSLT, результат абсолютно однаковий для паралельних та ітеративних реалізацій. Але для новачків XSLT, які мають загальний досвід, це допомагає уявляти собі <xsl:apply-templates>як певний цикл для кожного циклу, навіть якщо - технічно - це не так.
Томалак

@Tomalak: Хоча це може бути корисним для початківців програмістів XSLT, я думаю, що це часто вводить їх в оману, оскільки вони думають, що вони можуть повторно використовувати інформацію про стан, накопичену при "виконанні циклу".
Димитрій Новатчев

@Tomalak: Через ці факти я думаю, що було б доречно змінити "xsl: apply-templates is loop" з somethinkg на зразок: "xsl: apply-templates is like a loop"
Димитрей Новатчев

@Tomalak: Цикл - це ітерація, щось apply-templatesі call-templateінструкції не для. Вони є механізмом рекурсії в XSLT. І як відповів Дімітре, шаблони застосування - це поліморфізм або механізм, керований даними.

15

Щоб додати добру відповідь від @Tomalak:

Ось кілька неозначених та важливих відмінностей :

  1. xsl:apply-templatesнабагато багатший і глибший xsl:call-templatesі навіть від xsl:for-each, просто тому, що ми не знаємо, який код буде застосовано до вузлів вибору - в загальному випадку цей код буде різним для різних вузлів списку вузлів.

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

Бібліотека 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


8

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

Функціонал дійсно схожий (крім викликової семантики, де call-templateпотрібен nameатрибут та відповідний шаблон імен).

Однак аналізатор не виконає так само.

Від MSDN :

На відміну від цього <xsl:apply-templates>, <xsl:call-template>не змінює поточний вузол чи поточний список вузлів.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.