2009-05-18 13 views
1

私はXSLTテンプレートのオーバーライドに関する小さな質問があります。 は私のXMLのこのセグメントのために:私のXSLTシートでXSLTテンプレートのオーバーライド

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

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

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

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

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

私は入力と同じXMLを取得していますが、要素をテキストで置き換えていません。 2番目のテンプレートが一致する理由は、最初のテンプレートのname要素を上書きしないのですか?事前のおかげで

- アリ

答えて

2

はあなた<xsl:template match="medicine/name">

<xsl:template match="@*|node()"> 
    <xsl:copy> 
    <xsl:apply-templates select="@*|node()"/> 
    </xsl:copy> 
</xsl:template> 

を追加し、完全<xsl:template match="medication">を削除!

<?xml version="1.0" encoding="windows-1251"?> 
<xsl:stylesheet 
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
     version="1.0"> 

<xsl:template match="medicine/name"> 
    <text>!unauthorized information!</text> 
</xsl:template> 

<xsl:template match="@*|node()"> 
    <xsl:copy> 
    <xsl:apply-templates select="@*|node()"/> 
    </xsl:copy> 
</xsl:template> 

</xsl:stylesheet> 
+0

回答alamarに感謝します。これは多くの他の要素を持つ大きなXMLの塊であるため、投薬テンプレートを削除することはできません。ですから、最初はmedication要素をそのまま表示したいと思いますが、名前のようなテンプレート規則があればそれをテキストで置き換えます。希望を明確にする。 –

+0

さて、あなたにも述べることができる ます。 ます。 alamar

5

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

あなたのケースでは、テンプレートの優先度に問題はありません。 2つの異なるテンプレートルールがあります.1つは<medication>要素と一致し、もう1つは<name>要素に一致します。これらはと決してが衝突するので、テンプレートの優先順位や上書きの問題ではありません。問題は、あなたのコードが実際に<name>要素にテンプレートを適用することはないということです。 を<medication>と言うときは、「<medication>の深いコピーを実行する」と言っています。 <xsl:apply-templates/>

私があなたのために持っている解決策は基本的にalamarと同じですが、それは別の処理 "モード"を使用することを除いて、テンプレートルールのいずれかが子孫ノードに対して発火する唯一の方法です、これはあなたのスタイルシート内の他のすべてのルールからルールを分離します。一般的な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> 

""のルールは、 "@* | node()"のルールを上書きします。これは、p attern( "/"を含む)は、デフォルトの優先度(0.5)をデフォルト優先度 "node()"(-1.0)よりも高くします。

私のウェブサイトの"How XSLT Works"に、テンプレート優先度の仕組みの完全で簡潔な説明があります。

最後に、「RAW XML」をユーザーに表示することに気付きました。これは、たとえば、すべての開始タグと終了タグを含むXMLをブラウザに表示することを意味しますか?その場合は、すべてのマークアップをエスケープする必要があります(たとえば、「<」の場合は「&lt;」)。私のウェブサイトのXML-to-string utilityをチェックしてください。あなたがそれを使用する方法の例が必要かどうか私に教えてください。

関連する問題