1

XSLT テンプレートのオーバーライドに関してちょっとした質問があります。XML のこのセグメントの場合:

<record>
  <medication>
    <medicine>
      <name>penicillin G</name>
      <strength>500 mg</strength>
    </medicine>
  </medication>
</record>

私の XSLT シートには、次の順序で 2 つのテンプレートがあります。

 <xsl:template match="medication">
   <xsl:copy-of select="." />
   </xsl:template>
   <xsl:template match="medicine/name">
   <text>!unauthorized information!</text>
 </xsl:template>

私がやりたいことは、投薬要素の下にあるすべてを、「名前」要素 (または明示的に定義した他の要素) 以外の出力にコピーすることです。最終的な xml は、RAW XML 形式でユーザーに表示されます。言い換えれば、私が望む結果は次のとおりです。

<record>
  <medication>
    <medicine>
      <text>! unauthorized information!</text>
      <strength>500 mg</strength>
    </medicine>
  </medication>
</record>

一方、入力と同じ XML を取得しています。つまり、要素がテキストに置き換えられていません。2 番目のテンプレートの一致が最初の名前要素を上書きしない理由はありますか? 前もって感謝します

-- アリ

4

2 に答える 2

5

テンプレートの順序は関係ありません。考慮される可能性がある唯一のケース (これはプロセッサに依存します) は、解決できない競合、つまりエラー状態がある場合です。その場合、XSLT プロセッサが最後に発生したものを選択してエラーから回復することは合法です。ただし、この動作に依存するコードを記述しないでください。

あなたの場合、テンプレートの優先度は問題ではありません。<medication>一致する要素と一致する要素の 2 つの異なるテンプレート ルールがあり<name>ます。これらは決して衝突しないので、テンプレートの優先度やオーバーライドの問題ではありません。問題は、コードが実際にテンプレートを<name>要素に適用しないことです。<xsl:copy-of select="."/>onと言うときは、「<medication>のディープ コピーを実行する」と言っているのです<medication>。テンプレート ルールのいずれかが子孫ノードに対して起動する唯一の方法は、明示的にテンプレートを適用する場合です ( <xsl:apply-templates/>.

私があなたのために持っている解決策は、スタイルシートの他のすべてのルールからルールを分離する別の処理「モード」を使用することを除いて、基本的にアラマーのものと同じです。汎用match="@* | node()"テンプレートにより、テンプレート ルールが子 (および属性) に再帰的に適用されるため、特定のノードの動作をオーバーライドできます。

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

  <!-- ...placeholder for the rest of your code... -->
  <xsl:template match="/record">
    <record>
      <xsl:apply-templates/>
    </record>
  </xsl:template>
  <!-- end of placeholder -->

  <xsl:template match="medication">
    <!-- Instead of copy-of, whose behavior is to always perform
         a deep copy and cannot be customized, define your own
         processing mode. Rules with this mode name are isolated
         from the rest of your code. -->
    <xsl:apply-templates mode="copy-medication" select="."/>
  </xsl:template>

          <!-- By default, copy all nodes and their descendants -->
          <xsl:template mode="copy-medication" match="@* | node()">
            <xsl:copy>
              <xsl:apply-templates mode="copy-medication" select="@* | node()"/>
            </xsl:copy>
          </xsl:template>

          <!-- But replace <name> -->
          <xsl:template mode="copy-medication" match="medicine/name">
            <text>!unauthorized information!</text>
          </xsl:template>

</xsl:stylesheet>

" "の規則は " medicine/name" の規則をオーバーライドします。@* | node()これは、パターン (" /" を含む) の形式により、デフォルトの優先度 (0.5) が " node()" のデフォルトの優先度 (-1.0) よりも高くなるためです。

テンプレートの優先度がどのように機能するかについての完全かつ簡潔な説明は、私の Web サイトの「XSLT の仕組み」にあります。

最後に、「RAW XML」をユーザーに表示したいとおっしゃっていました。それは、たとえば、すべての開始タグと終了タグを含む XML をブラウザーで表示したいということですか? その場合、すべてのマークアップをエスケープする必要があります (例: " &lt;" を " <")。私の Web サイトでXML から文字列へのユーティリティを調べてください。使用方法の例が必要な場合はお知らせください。

于 2009-05-18T18:56:42.637 に答える