16

それが可能かどうかはわかりませんが、どうすればいいのでしょうか...

次のXSLがあるとしましょう。

<xsl:template name="foo">
  Bla bla bla
</xsl:template>
...
<xsl:template name="bar">
  Bla bla bla
</xsl:template>
...
<xsl:template match="/">
  <xsl:if test="$templateName='foo'">
    <xsl:call-template name="foo"/>
  </xsl:if>
  <xsl:if test="$templateName='bar'">
    <xsl:call-template name="bar"/>
  </xsl:if>
</xsl:template>

XSLを変更して次のようなものを読み取ることは可能ですか...

<xsl:template match="/">
  <xsl:call-template name="$templateName"/>
</xsl:template>
4

7 に答える 7

13

説明どおりに実行することはできませんが、他の場所で設定した値に基づいて実行時にテンプレートを選択できるようにする場合は、それを行うためのトリックがあります。名前付きテンプレートを、別のモードで対応する名前のノードと一致させて(通常の変換を台無しにしないようにするため)、それに一致させるという考え方です。例えば:

<xsl:stylesheet ... xmlns:t="urn:templates">

  <!-- Any compliant XSLT processor must allow and ignore any elements 
       not from XSLT namespace that are immediate children of root element -->
  <t:templates>
    <t:foo/>
    <t:bar/>
  </t:templates>

  <!-- document('') is the executing XSLT stylesheet -->     
  <xsl:variable name="templates" select="document('')//t:templates" />

  <xsl:template name="foo" match="t:foo" mode="call-template">
    Bla bla bla
  </xsl:template>

  <xsl:template name="bar" match="t:foo" mode="call-template">
    Bla bla bla
  </xsl:template>

  <xsl:template match="/">
    <xsl:variable name="template-name" select="..." />
    <xsl:apply-templates select="$templates/t:*[local-name() = $template-name]"
                         mode="call-template"/>
  </xsl:template>

<xsl:with-param>で使用できることに注意してください。<xsl:apply-templates>これにより、プレーンで実行できるすべてのことを実行できます<xsl:call-template>

また、上記のコードは、XSLT拡張機能の使用を回避しようとするため、必要なコードよりもいくらか長くなります。プロセッサがをサポートしている場合は、を使用しexslt:node-set()てノードを直接生成し、ハックすることなく、結果のツリーフラグメントをプレーンノードに変換して照合することができます。<xsl:element>node-set()document('')

詳細については、FXSLを参照してください。FXSLは、この概念に基づくXSLTの関数型プログラミングライブラリです。

于 2009-08-05T22:09:58.537 に答える
6

いいえ、これは直接不可能ではありません。呼び出し規約は次のとおりです。

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

QNameが次のように定義されている場合:

QName ::= PrefixedName | UnprefixedName

PrefixedName   ::= Prefix ':' LocalPart
UnprefixedName ::= LocalPart

Prefix         ::= NCName
LocalPart      ::= NCName

基本的に、これは「文字のみ、表現なし」に要約されます。他の回答が強調しているように、実際には同等のことを行う方法がありますが、単純なアプローチ/ナイーブなアプローチは機能しません。

于 2009-08-05T16:00:37.333 に答える
3

誰かの将来の参考のために:

これは、PavelMinaevの回答に基づいた実用的な例です。私の側には独自の考えはありません。;-) .NETで機能するように、彼が説明したように(多かれ少なかれ)msxml:node-setを使用するように切り替えました。

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" version="1.0">
    <xsl:variable name="templates">
        <templates>
            <foo />
            <bar />
        </templates>
    </xsl:variable>
    <xsl:template name="foo" match="foo" mode="call-template">
        <FooElement />
    </xsl:template>
    <xsl:template name="bar" match="bar" mode="call-template">
        <BarElement />
    </xsl:template>
    <xsl:template match="/">
        <Root>
            <xsl:variable name="template-name">bar</xsl:variable> <!-- Change this to foo to get the other template. -->
            <xsl:apply-templates select="msxsl:node-set($templates)/*/*[local-name() = $template-name]" mode="call-template" />
        </Root>
    </xsl:template>
</xsl:stylesheet>
于 2013-07-18T16:00:04.207 に答える
2

更新:以下のリンクは、web.archive.orgを指すように更新されました。残念ながら、IDEALLIANCEにより、すべてのExteme Markup Languages会議の議事録が利用できなくなりました...やがて、これら2つの記事のより永続的な場所が見つかります。


これはFXSLに実装されています。

FXSLの主な原則についての良い説明があります。

次の2つの記事を参照してください。

FXSLライブラリを使用したXSLTでの関数型プログラミング」(XSLT 1.0の場合)、(PDF):

http://web.archive.org/web/20070710091236/http://www.idealliance.org/papers/extreme/proceedings/xslfo-pdf/2003/Novatchev01/EML2003Novatchev01.pdf

(HTML)で:

http://conferences.idealliance.org/extreme/html/2003/Novatchev01/EML2003Novatchev01.html



XSLT2.0およびFXSLを使用した高階関数型プログラミング」(PDF):

http://web.archive.org/web/20070222111927/http://www.idealliance.org/papers/extreme/proceedings/xslfo-pdf/2006/Novatchev01/EML2006Novatchev01.pdf

(HTML):http: //conferences.idealliance.org/extreme/html/2006/Novatchev01/EML2006Novatchev01.html



FXSLを使用して、「XSLTでは不可能」と思われる多くの問題を簡単かつエレガントに解決することができました。ここにはたくさんの例があります。

于 2009-08-06T03:53:39.877 に答える
2

私はあなたと多かれ少なかれ同じ問題を抱えていたと思います。「外部」テンプレートがあり、実行時に設定された変数に応じて、別の「内部」テンプレートを呼び出したいと思いました。ダイナミックにする方法についてグーグルであなたの質問を見つけました<xsl:call-template><xsl:apply-templates>代わりに次のように使って解決しました。

入力XML(実行時に生成される)には、次の行に沿って何かが含まれています。

<template name="template_name_1"/>

「外部」テンプレートのXSLには次のものがあります。

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

select="template"このapply-templatesは<template>、入力XMLのタグを参照しています)

nameそして最後に、XMLの属性の値の結果として含めたい「内部」テンプレートは、次のようになります。

<xsl:template match="template[@name='template_name_1']">
    <!-- XSL / XHTML goes here -->
</xsl:template>

(ここでも、はmatch="template[@name='xyz']"前のものを参照し、select="template"次に入力XMLの<template>タグとその属性を参照します)name

このようにして、入力XMLから制御するだけで、動的に「呼び出される」テンプレートを作成できます。

これはあなたが解決しようとしているのと同じ問題ではないかもしれませんが、私はそれがかなり近く、このページの他の場所で言及されているFSXLソリューションよりもはるかに単純だと思います。

于 2013-03-29T19:22:57.163 に答える
0

これはどうですか?:

  <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

      <xsl:template match="xsl:template[@name='foo']" name="foo">
    Bla bla bla foo
      </xsl:template>

      <xsl:template match="xsl:template[@name='bar']" name="bar">
    Bla bla bla bar
      </xsl:template>

      <xsl:template match="/">
        <xsl:variable name="templateName" select="'bar'"/>
        <xsl:apply-templates select="document('')/*/xsl:template[@name=$templateName]"/>
        <xsl:apply-templates select="document('')/*/xsl:template[@name='foo']"/>
      </xsl:template>

    </xsl:stylesheet>

以前の寄稿で説明したのと同様に、変数を使用してテンプレートの「呼び出し」を簡略化できます。

<xsl:variable name="templates" select="document('')/*/xsl:template"/> 

<xsl:apply-templates select="$templates[@name=$templateName]"/>
<xsl:apply-templates select="$templates[@name='foo']"/>

オプション<xsl:with-param>は通常通り使用できることに注意してください。

于 2015-02-11T15:28:51.257 に答える
0

素晴らしい答えをありがとう@Pavel、@Dimitre。これは、将来の参照のために@Pavelのアプローチを基本的にリサイクルする別の実用的な例です...

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  

  <xsl:variable name="templates">
    <xsl:for-each select="('foo','bar')">
      <xsl:element name="{.}"/>
    </xsl:for-each>
  </xsl:variable>
  
  <xsl:template name="foo" match="foo" mode="call-template">
    Foo foo foo
  </xsl:template>
  
  <xsl:template name="bar" match="bar" mode="call-template">
    Bar bar bar
  </xsl:template>
  
  <xsl:template match="/">
  
    <xsl:for-each select="('bar','foo','foo','bar')">
      <xsl:variable name="template-name" select="." />
      <xsl:apply-templates select="$templates/*[local-name() = $template-name]"  mode="call-template"/>
    </xsl:for-each>
    
    
  </xsl:template>

</xsl:stylesheet>
于 2021-11-02T15:25:08.647 に答える