Apa perbedaan antara 'call-template' dan 'apply-templates' di XSL?

119

Saya baru di XSLT jadi saya sedikit bingung tentang kedua tag tersebut,

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

dan

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

Jadi bisakah Anda membuat daftar perbedaan di antara mereka?

Venkat
sumber

Jawaban:

167

<xsl:call-template> sangat mirip dengan memanggil fungsi dalam bahasa pemrograman tradisional.

Anda dapat mendefinisikan fungsi di XSLT, seperti yang sederhana ini yang menghasilkan string.

<xsl:template name="dosomething">
  <xsl:text>A function that does something</xsl:text>
</xsl:template>

Fungsi ini dapat dipanggil melalui <xsl:call-template name="dosomething">.

<xsl:apply-templates>sedikit berbeda dan di dalamnya adalah kekuatan nyata XSLT: Dibutuhkan sejumlah node XML (apa pun yang Anda tentukan dalam selectatribut), mengulanginya ( ini penting: apply-templates bekerja seperti loop! ) dan menemukan templat yang cocok untuk mereka:

<!-- 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>

Dengan cara ini Anda melepaskan sedikit kendali ke prosesor XSLT - bukan Anda memutuskan ke mana aliran program, tetapi prosesor melakukannya dengan menemukan kecocokan yang paling sesuai untuk node yang sedang diproses.

Jika beberapa template dapat cocok dengan sebuah node, yang memiliki ekspresi pencocokan yang lebih spesifik menang. Jika ada lebih dari satu template yang cocok dengan kekhususan yang sama, yang terakhir dinyatakan menang.

Anda dapat lebih berkonsentrasi pada pengembangan template dan membutuhkan lebih sedikit waktu untuk melakukan "pemipaan". Program Anda akan menjadi lebih kuat dan termodulasi, tidak terlalu dalam dan lebih cepat (karena prosesor XSLT dioptimalkan untuk pencocokan template).

Sebuah konsep untuk dipahami dengan XSLT adalah konsep "simpul saat ini". Dengan <xsl:apply-templates>node saat ini bergerak dengan setiap iterasi, sedangkan <xsl:call-template>node saat ini tidak berubah. Yaitu di .dalam template yang dipanggil merujuk ke node yang sama seperti .di template panggilan. Ini tidak terjadi dengan apply-templates.

Inilah perbedaan mendasar. Ada beberapa aspek lain dari templat yang memengaruhi perilakunya: Mereka modedan priority, fakta bahwa templat dapat memiliki a namedan a match. Ini juga berdampak apakah template telah diimpor ( <xsl:import>) atau tidak. Ini adalah penggunaan tingkat lanjut dan Anda dapat mengatasinya saat Anda sampai di sana.

Tomalak
sumber
5
@Tomalak: Jawaban bagus! Namun, pernyataan: "xsl: apply-templates is a loop" tidak benar. Tidak ada indikasi dalam spesifikasi W3C resmi yang <xsl:apply-templates>harus diimplementasikan sebagai loop - sebaliknya, ini dapat diterapkan secara paralel, karena aplikasi yang berbeda pada node yang berbeda dari daftar node benar-benar independen satu sama lain.
Dimitre Novatchev
8
@Dimitre: Yang ingin saya katakan: Dari perspektif pengguna akhir, <xsl:apply-templates>berperilaku seperti lingkaran. Perbedaan implementasi pada ujung prosesor XSLT tidak akan mempengaruhi saya sebagai programmer XSLT, hasilnya benar-benar sama untuk implementasi paralel dan berulang. Tetapi untuk seorang pemula XSLT dengan latar belakang yang penting, itu membantu untuk membayangkan <xsl:apply-templates>sebagai semacam loop untuk setiap, bahkan jika - secara teknis - tidak.
Tomalak
@Tomalak: Meskipun ini mungkin berguna untuk pemrogram XSLT pemula, saya pikir ini sering menyesatkan bagi mereka karena mereka berpikir bahwa mereka dapat menggunakan kembali informasi negara yang terkumpul dalam "eksekusi loop".
Dimitre Novatchev
@Tomalak: Karena fakta-fakta ini, saya pikir akan tepat untuk mengubah "xsl: apply-templates is a loop" dengan sesuatu seperti: "xsl: apply-templates is like a loop"
Dimitre Novatchev
@Tomalak: Loop adalah iterasi, sesuatu apply-templatesdan call-templateinstruksi bukan untuk. Mereka adalah mekanisme rekursi di XSLT. Dan seperti yang dijawab Dimitre, apply-templates adalah polimorfisme atau mekanisme yang digerakkan oleh data.
15

Untuk menambah jawaban bagus oleh @Tomalak:

Berikut adalah beberapa perbedaan penting dan tidak disebutkan :

  1. xsl:apply-templatesjauh lebih kaya dan lebih dalam daripada xsl:call-templatesdan bahkan dari xsl:for-each, hanya karena kita tidak tahu kode apa yang akan diterapkan pada node pilihan - dalam kasus umum kode ini akan berbeda untuk node yang berbeda dari daftar node.

  2. Kode yang akan diterapkan dapat ditulis dengan cara setelah xsl:apply templates ditulis dan oleh orang yang tidak mengetahui penulis aslinya.

The FXSL perpustakaan 's pelaksanaan fungsi tingkat tinggi (HOF) di XSLT tidak akan mungkin jika XSLT tidak memiliki <xsl:apply-templates>instruksi.

Ringkasan : Template dan <xsl:apply-templates>instruksinya adalah bagaimana XSLT mengimplementasikan dan menangani polimorfisme.

Referensi : Lihat seluruh utas ini: http://www.biglist.com/lists/lists.mulberrytech.com/xsl-list/archives/200411/msg00546.html

Dimitre Novatchev
sumber
8

xsl:apply-templatesbiasanya (tetapi tidak harus) digunakan untuk memproses semua atau sebagian dari turunan node saat ini dengan semua template yang berlaku. Ini mendukung rekursif aplikasi XSLT yang cocok dengan (kemungkinan) rekursif XML yang diproses.

xsl:call-templatedi sisi lain lebih seperti panggilan fungsi biasa. Anda menjalankan persis satu template (bernama), biasanya dengan satu atau lebih parameter.

Jadi saya gunakan xsl:apply-templatesjika saya ingin mencegat pemrosesan node yang menarik dan (biasanya) menyuntikkan sesuatu ke dalam aliran keluaran. Contoh tipikal (disederhanakan) adalah

<xsl:template match="foo">
  <bar>
    <xsl:apply-templates/>
  </bar>
</xsl:template>

sedangkan dengan xsl:call-templatesaya biasanya memecahkan masalah seperti menambahkan teks dari beberapa subnode bersama-sama, mengubah node yang dipilih menjadi teks atau node lain dan sejenisnya - apa pun yang Anda ingin tulis, fungsi khusus yang dapat digunakan kembali.

Edit:

Sebagai komentar tambahan untuk teks pertanyaan spesifik Anda:

<xsl:call-template name="nodes"/> 

Ini memanggil template yang dinamai 'node':

    <xsl:template name="nodes">...</xsl:template>

Ini adalah semantik yang berbeda dari:

<xsl:apply-templates select="nodes"/>

... yang menerapkan semua template ke semua turunan node XML Anda saat ini yang namanya 'node'.

TToni
sumber
2

Fungsinya memang serupa (selain dari semantik pemanggil, di mana call-templatemembutuhkan nameatribut dan templat nama yang sesuai).

Namun, parser tidak akan mengeksekusi dengan cara yang sama.

Dari MSDN :

Tidak seperti <xsl:apply-templates>, <xsl:call-template>tidak mengubah node saat ini atau daftar node saat ini.

Oded
sumber