wake-up-neo.com

Warum gibt XSLT standardmäßig den gesamten Text aus?

Hallo, ich hatte eine Transformation durchgeführt, die ein Tag löscht, wenn es null ist.

Ich wollte überprüfen, ob meine Transformation einwandfrei funktioniert. Anstatt sie manuell zu überprüfen, schrieb ich einen weiteren XSLT-Code, der nur das Vorhandensein dieses bestimmten Tags in der OUTPUT-XML prüft. Wenn es null ist, sollte der zweite XSLT ein ausgeben Text "GEFUNDEN". (Ich brauche eigentlich keine XML-Ausgabe, sondern verwende nur XSLT für die Suche.)

Als ich es mit diesem XSL-Code versuchte:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="/SiebelMessage//SuppressCalendar[.!='']">
      FOUND
  </xsl:template>
</xsl:stylesheet>

Es gibt alle in der XML-Datei vorhandenen TEXTDATEN aus.

um das zu vermeiden, musste ich diesen Code schreiben:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="/SiebelMessage//SuppressCalendar[.!='']">
      FOUND
  </xsl:template>
  <xsl:template match="text()"/>
</xsl:stylesheet>

warum gab der frühere Code TEXT aus, warum sollte ich XSL darauf bestehen, allen anderen Text zu ignorieren? ist, dass das Verhalten aller XML-Parser oder nur meiner eigenen (ich verwende Msxml-Parser).

71

warum gab der frühere Code TEXT aus, warum sollte ich auf XSL bestehen, um allen anderen Text zu ignorieren? ist, dass das Verhalten aller XML-Parser oder nur meiner eigenen

Sie entdecken eine der grundlegendsten XSLT-Funktionen, wie in der Spezifikation angegeben: die integrierten Vorlagen von XSLT.

Von der Spezifikation:

Es gibt eine integrierte Vorlagenregel, mit der die rekursive Verarbeitung fortgesetzt werden kann, wenn keine erfolgreiche Musterübereinstimmung durch eine explizite Vorlagenregel im Stylesheet erfolgt. Diese Vorlagenregel gilt sowohl für Elementknoten als auch für den Stammknoten. Das Folgende zeigt das Äquivalent der integrierten Vorlagenregel:

<xsl:template match="*|/">
  <xsl:apply-templates/>
</xsl:template>

Es gibt auch eine integrierte Vorlagenregel für jeden Modus, mit der die rekursive Verarbeitung im selben Modus fortgesetzt werden kann, wenn keine erfolgreiche Musterübereinstimmung durch eine explizite Vorlagenregel im Stylesheet erfolgt. Diese Vorlagenregel gilt sowohl für Elementknoten als auch für den Stammknoten. Das Folgende zeigt das Äquivalent der integrierten Vorlagenregel für Modus m.

<xsl:template match="*|/" mode="m">
  <xsl:apply-templates mode="m"/>
</xsl:template>

Es gibt auch eine integrierte Vorlagenregel für Text- und Attributknoten, die Text kopiert über:

<xsl:template match="text()|@*">
  <xsl:value-of select="."/>
</xsl:template>

Die eingebaute Vorlagenregel für die Verarbeitung von Anweisungen und Kommentaren soll nichts bewirken.

<xsl:template match="processing-instruction()|comment()"/>

Die integrierte Vorlagenregel für Namespace-Knoten hat ebenfalls nichts zu tun. Es gibt kein Muster, das mit einem Namespace-Knoten übereinstimmen kann. Daher ist die integrierte Vorlagenregel die einzige Vorlagenregel, die für Namespace-Knoten angewendet wird.

Die integrierten Vorlagenregeln werden so behandelt, als wären sie implizit vor dem Stylesheet importiert worden und haben daher eine niedrigere Importpriorität als alle anderen Vorlagenregeln. Auf diese Weise kann der Autor eine integrierte Vorlagenregel überschreiben, indem er eine explizite Vorlagenregel einfügt.

Das gemeldete Verhalten ist also das Ergebnis der Anwendung der integrierten Vorlagen - die erste und die zweite von allen dreien.

Es ist ein gutes XSLT-Entwurfsmuster, die eingebauten Vorlagen mit Ihren eigenen zu überschreiben, die bei jedem Aufruf eine Fehlermeldung ausgeben, damit der Programmierer seine sofort kennt Transformation ist "undicht":

Zum Beispiel , wenn es dieses XML-Dokument gibt:

<a>
  <b>
    <c>Don't want to see this</c>
  </b>
</a>

und es wird mit dieser Transformation verarbeitet :

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="a|b">
   <xsl:copy>
      <xsl:attribute name="name">
        <xsl:value-of select="name()"/>
      </xsl:attribute>
      <xsl:apply-templates/>
   </xsl:copy>
 </xsl:template>
</xsl:stylesheet>

das Ergebnis ist :

<a name="a">
   <b name="b">Don't want to see this</b>
</a>

und der Programmierer wird sehr verwirrt sein, wie der unerwünschte Text erschien.

Durch einfaches Hinzufügen von catch-all template können Sie solche Verwirrungen vermeiden und Fehler sofort abfangen :

 <xsl:template match="*">
  <xsl:message terminate="no">
   WARNING: Unmatched element: <xsl:value-of select="name()"/>
  </xsl:message>

  <xsl:apply-templates/>
 </xsl:template>

Jetzt erhält der Programmierer neben der verwirrenden Ausgabe eine Warnung, die das Problem sofort erklärt :

 WARNING: Unmatched element: c

Späterer Zusatz von Michael Kay für XSLT 3.0

In XSLT 3.0 können Sie das Fallback-Verhalten in einer xsl:mode - Deklaration angeben, anstatt eine Sammelvorlagenregel hinzuzufügen. Beispiel: Mit <xsl:mode on-no-match="shallow-skip"/> Werden alle nicht übereinstimmenden Knoten (einschließlich Textknoten) übersprungen, während mit <xsl:mode on-no-match="fail"/> Eine Nichtübereinstimmung als Fehler behandelt wird und mit <xsl:mode warning-on-no-match="true"/> eine Warnung.

146

In XSL gibt es mehrere eingebaute Vorlagenregeln , von denen eine folgende ist:

<xsl:template match="text()|@*">
  <xsl:value-of select="."/>
</xsl:template>

Es gibt Text aus.

14
Oded