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


118

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

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

そして

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

では、それらの違いを挙げてください。

回答:


166

<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の真の力は少し異なり、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には当てはまりません。

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


5
@トマラック:いい答えです!ただし、「xsl:apply-templates is a loop」という文は正しくありません。<xsl:apply-templates>ループとして実装する必要のある公式のW3C仕様には何も示されていません。逆に、ノードリストの異なるノードの異なるアプリケーションは互いに完全に独立しているため、並列に実装できます。
Dimitre Novatchev

8
@Dimitre:私が言いたかったこと:エンドユーザーの観点から<xsl:apply-templates>は、ループのように動作します。XSLTプロセッサ側の実装の違いは、XSLTプログラマとしての私には影響しません。結果は、並列化された実装と反復的な実装の両方でまったく同じです。しかし、命令的な背景を持つXSLT初心者にとっては<xsl:apply-templates>、たとえ技術的にはそうでなくても、一種のfor-eachループとして想像することは役立ちます。
Tomalak

@Tomalak:これは初心者のXSLTプログラマーには役立つかもしれませんが、「ループの実行」で蓄積された状態情報を再利用できると考えるので、彼らを誤解することが多いと思います。
Dimitre Novatchev 2010

@Tomalakは:これらの事実なので、私はそれを修正するのが適切だろうと思い、「XSLを:適用-テンプレートはループです」のようなsomethinkgと:「XSL:適用-テンプレートはあるようにループ」
Dimitre Novatchev

@Tomalak:ループは、反復、何かであるapply-templatescall-template命令がためにされていません。これらは、XSLTの再帰メカニズムです。そして、Dimitreが答えたように、apply-templatesはポリモーフィズムまたはデータ駆動型のメカニズムです。

15

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

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

  1. xsl:apply-templatesxsl:call-templatesxsl:for-each選択範囲のノードに適用されるコードがわからないためから よりもさらに深く、より一般的です-一般に、このコードはノードリストのノードごとに異なります。

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

XSLTに<xsl:apply-templates>命令がない場合FXSLライブラリのXSLTでの高次関数(HOF)の実装は不可能です。

要約:テンプレートと<xsl:apply-templates>命令は、XSLTがどのようにポリモーフィズムを実装して処理するかです。

参照:このスレッド全体を参照してください:http : //www.biglist.com/lists/lists.mulberrytech.com/xsl-list/archives/200411/msg00546.html


8

xsl:apply-templates通常(必須ではありません)は、現在のノードの子のすべてまたはサブセットを適用可能なすべてのテンプレートで処理するために使用されます。これは、処理された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ノードのすべての子にすべてのテンプレートを適用します。


2

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

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

MSDNから:

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.