web-dev-qa-db-ja.com

「apply-templates」を使用したXSL名前付きパラメーター「with-param」

完全な説明の前に読みたい場合、私の質問はこの投稿の下部にあります。

XSLを使用してXMLドキュメントをきれいなWebページに変換していますが、変数を正しく渡すことに問題があります。多くのxsl:templatesを定義しており、そのうちの1つに特定のパラメーターを渡す必要があります。おそらくすべてのxsl:templatesに送信される名前付きパラメーターを渡すことができると期待していましたが、単一のパラメーターでのみ使用され、他のパラメーターでは無視されます。ただし、これを自分で(そしてXSLの理解が限られて)テストしようとすると、パラメーターを渡すことができず、他のxsl:templatesを誤って妨害していないかどうかをテストできませんでした。

以下は、コード例を簡略化したものです(この質問に対して入力されたもので、タイプミスまたは2つが含まれる場合があります)。 XMLのノードを処理するために多くのさまざまなxsl:templatesを定義しており、現在まですべてが正常に機能しています。これらのテンプレートにパラメーターを追加する際に問題が発生しているようです。

XMLファイル:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="main.xsl"?>
<wrapperNode>
  <testNode>
    <subNode/>
  </testNode>
</wrapperNode>

main.xsl:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:import href="test.xsl"/>
<xsl:output method="html" indent="yes"/>

<xsl:template match="/">

<html>
  <body>
      <xsl:apply-templates>
        <xsl:with-param name="testParam">TEST_PARAMETER</xsl:with-param>
      </xsl:apply-templates>
  </body>
</html>

</xsl:template>
</xsl:stylesheet>

test.xsl:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="testNode">
  <xsl:param name="testParam" />
  TEST1
  <xsl:value-of select="$testParam" />
  TEST2
</xsl:template>
</xsl:stylesheet>

出力(実際):

TEST1 TEST2

出力(予想/望ましい):

TEST1 TEST_PARAMETER TEST2

これに関する私の質問:

  1. 名前付きパラメーターをxsl:templatexsl:apply-templatesを使用してすべてのxsl:with-paramsに送信することは可能ですか?ただし、実際のテンプレート内でname=によってこの値を具体的に選択して単一のテンプレートで明示的に使用され、他のすべてのテンプレートで無視されますか(後で他のテンプレートに別の名前の異なるパラメーターを追加したい場合でも)。

  2. 現在のサンプルコードで、パラメーターをまったく受け取っていないように見えるのはなぜですか。

  3. これを達成するためのより良い方法はありますか?

編集:test.xsltestNodeテンプレート内の他の出力により、それが確実にわかることを明確にしたい[〜#〜] is [〜#〜]が正常に呼び出されています。 [〜#〜] only [〜#〜]が機能していないパラメーター部分です。そのテンプレートが呼び出されない理由を理解するために人々の時間を無駄にするつもりはありません。そうです。

更新:私が最初に受け取った回答に応えて、私が作成した例は完全に正確ではなく(私の間違い)、問題をあまり明確に示さなかった(つまり、正しいテンプレートisが呼び出されていますが、onlyパラメータが機能していないようです)、私は例をはるかに良いものに置き換えました。この例は、testNodeテンプレートが正常に呼び出されているが、パラメーターが渡されていないように見えることをより明確に示しています。この質問に対する以前の回答を検討する前後に、私はこれを何度もテストしました。私が他で読んだことや、これまでに人々が提案したことから、すべてが正しいように見えるので、私は絶対に困惑しています。

18
KevenK

これに関する私の質問:

  1. Xsl:with-paramでxsl:apply-templatesを使用してすべてのxsl:templatesに名前付きパラメーターを送信することは可能ですか?単一のテンプレートであり、他のすべてのテンプレートで無視されます(後で他のテンプレートに別の名前の異なるパラメーターを追加したい場合でも)?

はい。 XSLT 2.0では、いわゆる「トンネルパラメータ」を使用できますが、XSLT 1.0ではこれは、いくつかのパラメータがチェーンのリモートテンプレートに到達する方法です。

もう1つの方法は、グローバルパラメーターを使用して、チェーン内のすべてのテンプレートを通過させる必要がないようにすることです。

.2。現在のサンプルコードで、パラメーターをまったく受け取っていないように見えるのはなぜですか。

理由は、私たちに見せていないコードにあります。または、実際のケースで使用しているソースXMLドキュメントが、ここで提供されているものと同じでない可能性があります。提供されたコードを実行しましたが、問題を再現できませんでした。目的の出力が生成されます。

私の推測は、testNodeに一致するテンプレートの前に他のテンプレートが選択されていることです。このテンプレートは、渡されたパラメータについて何も認識せず、次のテンプレートに渡しませんそれは、順番に適用されます。したがって、パラメータはtestNodeに一致するテンプレートにまったく渡されません。

私の推測では、置き換えた場合:

  <xsl:apply-templates> 
    <xsl:with-param name="testParam">TEST_PARAMETER</xsl:with-param> 
  </xsl:apply-templates> 

  <xsl:apply-templates select="testNode"> 
    <xsl:with-param name="testParam">TEST_PARAMETER</xsl:with-param> 
  </xsl:apply-templates> 

希望する出力を得ることができます。

また、XSLTデバッガー(Visual Studioのデバッガーなど)を使用してトレースし、どのテンプレートが選択されているかを正確に確認することもできます。

.3。これを達成するためのより良い方法はありますか?

前に述べたように、グローバルパラメータを代わりに使用できます-これがより良いかどうかはわかりません。

最後に、これはあなたの問題を再現できない私が実行したコードです:

XSLTスタイルシート

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" indent="yes"/>

 <xsl:template match="/">
      This is text1
      <xsl:apply-templates>
        <xsl:with-param name="testParam">TEST_PARAMETER</xsl:with-param>
      </xsl:apply-templates>
      This is text2
 </xsl:template>

 <xsl:template match="testNode">
  <xsl:param name="testParam" />
  <xsl:value-of select="$testParam" />
 </xsl:template>
</xsl:stylesheet>

XMLドキュメント

<?xml-stylesheet type="text/xsl" href="main.xsl"?>
<testNode>
  <subNode/>
</testNode>

結果

  This is text1
  TEST_PARAMETER
  This is text2

UPDATE:

OPは、私の推測を証明するより正確な情報を提供しています。

これで、要素ノードのXSLT組み込みテンプレートwrapperNodeに選択できるようにすることで問題が発生していることは明らかです。このテンプレートは、当然、パラメータについては何も認識せず、testParamパラメータを使用せず、このパラメータを通過させません。したがって、組み込みテンプレートの<xsl:apply-templates/>は、testNodeに一致するテンプレートが、パラメーターを渡さずに選択されるようにします。これは報告された動作/結果を説明します。

ソリューション:ソリューションは、wrapperNodeという名前のパラメーターを受け入れ、テンプレートを適用するときにそれを渡すtestParamに一致するテンプレートを指定することです。

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="html" indent="yes"/>

 <xsl:template match="/">
  <html>
    <body>
        <xsl:apply-templates>
          <xsl:with-param name="testParam" select="'TEST_PARAMETER'"/>
        </xsl:apply-templates>
    </body>
  </html>
 </xsl:template>

 <xsl:template match="testNode">
  <xsl:param name="testParam" />
  TEST1
  <xsl:value-of select="$testParam" />
  TEST2
 </xsl:template>

 <xsl:template match="wrapperNode">
  <xsl:param name="testParam" />

  <xsl:apply-templates>
   <xsl:with-param name="testParam" select="$testParam"/>
  </xsl:apply-templates>
 </xsl:template>
</xsl:stylesheet>

ここで、この変換が提供されたXMLドキュメントに適用されると、期待される結果が生成されます

<html>
<body>
  TEST1
  TEST_PARAMETER
  TEST2
 </body>
</html>
27

きみの <html>および<body>タグは、XSLスタイルシート内では使用できません。それらと終了タグを削除してOxygen/XMLで実行すると、「望ましい」出力が得られます。これらのタグをトップレベルのテンプレートの内側に置きたいと思います。その場合、htmlおよびbodyタグ内に出力が生成されます。

無効なスタイルシートについて不満を言わなかったXSLTエンジンはどれですか。

1
Jim Garrison

上記のポスターの3つのサンプルをそのまま実行し、XMLツールがインストールされたUbuntu 18.04の下のWineでNotepad ++ 7.7.1を使用してこの結果を得ました。

<html><body>

  TEST1
  TEST_PARAMETER
  TEST2

</body></html>
0
Peter Gruenbeck