2009-05-18 1 views
1

Ich habe eine kleine Frage in Bezug auf XSLT-Vorlage überschreiben. für dieses Segment meiner XML:XSLT-Vorlage überschreiben

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

In meinem XSLT Blatt, ich habe zwei Vorlagen in der folgenden Reihenfolge:

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

Was ich will ist alles tun, unter dem Medikation Elemente kopieren die Ausgabe anders als das Element "name" (oder jedes andere Element, das ich explizit definiere). Das endgültige XML wird dem Benutzer im RAW-XML-Format angezeigt. Mit anderen Worten, ich möchte das Ergebnis ist:

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

Während ich die gleiche XML als Eingabe immer bin, das heißt ohne das Element durch Text ersetzt. Irgendwelche Ideen, warum die zweite Vorlagenübereinstimmung das Namenselement in der ersten nicht überschreibt? Vielen Dank im Voraus

- Ali

Antwort

2

hinzufügen

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

zu Ihrem <xsl:template match="medicine/name">

Und <xsl:template match="medication"> ganz entfernen!

<?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

Danke für die Antwort Alamar. Ich kann die Medikationsvorlage nicht entfernen, da dies nur ein Teil eines größeren XML mit vielen anderen Elementen ist. Zuerst möchte ich sagen, dass alle Medikationselemente so angezeigt werden, wie sie sind, ABER wenn irgendeine Template-Regel folgt, wie der Name, dann ersetzen Sie diese durch Text. Hoffe das klärt sich. –

+0

Nun können Sie auch angeben alamar

5

Template-Reihenfolge spielt keine Rolle. Der einzige Fall, den es möglicherweise in Betracht zieht (und dies ist prozessorabhängig) ist, wenn Sie einen nicht auflösbaren Konflikt haben, d. H. Eine Fehlerbedingung. In diesem Fall ist es für den XSLT-Prozessor zulässig, den Fehler zu beheben, indem Sie den letzten auswählen. Sie sollten jedoch niemals Code schreiben, der von diesem Verhalten abhängt.

In Ihrem Fall ist Vorlagenpriorität nicht einmal das Problem. Sie haben zwei verschiedene Vorlagenregeln, eine passende <medication> Elemente und eine übereinstimmende <name> Elemente. Diese werden niemals kollidieren, also ist es keine Frage der Vorlagenpriorität oder des Überschreibens. Das Problem besteht darin, dass Ihr Code niemals Vorlagen auf das Element <name> anwendet. Wenn Sie <xsl:copy-of select="."/> auf <medication> sagen, sagen Sie: "führen Sie eine tiefe Kopie von " aus. Die einzige Möglichkeit, die Template-Regeln für untergeordnete Knoten auszulösen, ist, wenn Sie explizit Vorlagen anwenden (unter Verwendung von <xsl:apply-templates/>.

Die Lösung, die ich für Sie habe, ist im Grunde das gleiche wie Alamar, mit der Ausnahme, dass es eine separate Verarbeitung "Modus" verwendet , die isoliert die Regeln von allen anderen Regeln in Ihrem Stylesheet. die generische match="@* | node()" Vorlage verursacht Vorlage Regeln rekursiv auf Kinder angewendet werden (und Attribute), die Ihnen die Möglichkeit gibt, das Verhalten für bestimmte Knoten außer Kraft zu setzen.

<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> 

Die Regel für "medicine/name" überschreibt die Regel für "@* | node()", weil das Format der p attern (das ein "/" enthält) hat seine Standardpriorität (0,5) höher als die Standardpriorität von "node()" (-1.0).

Eine vollständige, aber präzise Beschreibung der Funktionsweise der Vorlagenpriorität finden Sie unter "How XSLT Works" auf meiner Website.

Schließlich bemerkte ich, dass Sie erwähnten, dass Sie "RAW XML" dem Benutzer anzeigen möchten. Möchten Sie beispielsweise das XML mit allen Start- und End-Tags in einem Browser anzeigen? In diesem Fall müssten Sie alle Markups (z. B. "&lt;" für "<") auskommentieren. Überprüfen Sie die XML-to-string utility auf meiner Website. Lassen Sie es mich wissen, wenn Sie ein Beispiel für die Verwendung benötigen.