web-dev-qa-db-ja.com

XSLの「call-template」と「apply-templates」の違いは何ですか?

私はXSLTが初めてなので、2つのタグについて少し混乱しています。

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

そして

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

それで、それらの違いをリストアップできますか?

114
Venkat

<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>は現在のノードを変更しません。つまり呼び出されたテンプレート内の.は、呼び出しテンプレートの.と同じノードを参照します。これは、apply-templatesには当てはまりません。

これが基本的な違いです。テンプレートの動作に影響を与えるテンプレートには、他にもいくつかあります:modepriority、テンプレートはnamematchの両方を持つことができるという事実。また、テンプレートがインポートされたかどうか(<xsl:import>)にも影響します。これらは高度な用途であり、そこに着いたら対処することができます。

155
Tomalak

@Tomalakによる良い答えに追加するには:

ここにいくつかの言及されていない重要な違いがあります

  1. xsl:apply-templatesxsl:call-templatesよりもはるかに豊かで深いです。さらにxsl:for-eachからでも、単にわからないからです選択のノードに適用されるコード-一般的な場合、このコードはノードリストの異なるノードで異なります。

  2. 適用されるコードは、xsl:apply templatesが書き込まれた後、元の作者を知らない人が書くことができます。

FXSLライブラリ のXSLTでの高次関数(HOF)の実装は、XSLTができなかった場合は不可能です<xsl:apply-templates>命令があります。

Summary:テンプレートと<xsl:apply-templates>命令は、XSLTがポリモーフィズムを実装および処理する方法です。

リファレンス:このスレッド全体を見る:http://www.biglist.com/lists/ lists.mulberrytech.com/xsl-list/archives/200411/msg00546.html

15

xsl:apply-templatesは通常、(必ずしもではないが)allの適用可能なテンプレートを使用して、現在のノードのすべてまたは子のサブセットを処理するために使用されます。これは、処理されたXMLの(可能性のある)再帰性に一致するXSLTアプリケーションの再帰性をサポートします。

一方、xsl:call-templateは、通常の関数呼び出しによく似ています。通常、1つまたは複数のパラメーターを使用して、1つの(名前付き)テンプレートを実行します。

そのため、興味深いノードの処理をインターセプトし、(通常)出力ストリームに何かを挿入する場合は、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"/>

...これは、名前が「nodes」である現在のXMLノードのすべての子にすべてのテンプレートを適用します。

7
TToni

機能は確かに似ています(呼び出しセマンティクスを除き、call-templateにはname属性と対応する名前テンプレートが必要です)。

ただし、パーサーは同じ方法で実行されません。

MSDN から:

<xsl:apply-templates>とは異なり、<xsl:call-template>は現在のノードまたは現在のノードリストを変更しません。

2
Oded