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

73

Hallo, ich habe eine Transformation durchgeführt, bei der ein Tag gelöscht wird, wenn es null ist.

Ich wollte überprüfen, ob meine Umwandlung einwandfrei funktioniert. Anstatt sie manuell zu überprüfen, habe ich einen weiteren XSLT-Code geschrieben, der nur das Vorhandensein dieses bestimmten Tags im OUTPUT-XML überprüft. Wenn es null ist, sollte das zweite XSLT a ausgeben Text "GEFUNDEN". (Ich benötige eigentlich keine XML-Ausgabe, aber ich 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 TEXTDATEN aus, die in der XML-Datei vorhanden sind.

Um dies 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 hat der frühere Code TEXT ausgegeben, warum sollte ich darauf bestehen, dass XSL den gesamten anderen Text ignoriert? ist, dass das Verhalten aller XML-Parser oder nur meiner eigenen (ich verwende msxml-Parser).

InfantPro'Aravind '
quelle

Antworten:

147

Warum hat der frühere Code TEXT ausgegeben, warum sollte ich darauf bestehen, dass XSL den gesamten anderen Text ignoriert? ist, dass das Verhalten aller XML-Parser oder nur meiner eigenen

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

Aus 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, mit der Text kopiert wird:

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

Die integrierte Vorlagenregel für die Verarbeitung von Anweisungen und Kommentaren lautet, nichts zu tun.

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

Die integrierte Vorlagenregel für Namespace-Knoten lautet auch, 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 ob sie implizit vor dem Stylesheet importiert wurden, 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 - der 1. und 2. von allen drei.

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

Wenn beispielsweise dieses XML-Dokument vorhanden ist:

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

Wenn Sie dies jedoch nur hinzufügen catch-all template, können Sie solche Verwirrungen vermeiden und Fehler sofort erkennen :

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

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

Neben der verwirrenden Ausgabe erhält der Programmierer nun 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 für eine xsl:modeDeklaration angeben, anstatt eine Sammelvorlagenregel hinzuzufügen . <xsl:mode on-no-match="shallow-skip"/>Verursacht beispielsweise, dass alle nicht übereinstimmenden Knoten (einschließlich Textknoten) übersprungen werden, während <xsl:mode on-no-match="fail"/>eine Nichtübereinstimmung als Fehler behandelt wird und <xsl:mode warning-on-no-match="true"/>eine Warnung ausgegeben wird.

Dimitre Novatchev
quelle
4
+1: Großartige Erklärung - viel vollständiger als die akzeptierte Antwort, obwohl die akzeptierte Antwort auch die spezifische Frage beantwortet.
Don Roby
@ Donroby: Danke. Warum sollte meine Antwort die Frage nicht beantworten und beantworten? Jeder, der dieses Problem hat und meine Antwort liest, wird die Ursache seines Problems verstehen und es beheben können.
Dimitre Novatchev
@donroby: Meine Antwort liefert eine genaue Antwort:"So, the reported behavior is the result of the application of the built-in templates -- the 2nd of all three of them"
Dimitre Novatchev
1
Ja, Ihre Antwort beantwortet auch die spezifische Frage. Wollte nicht anders implizieren. Die akzeptierte Antwort sollte nicht ausdrücklich abgelehnt werden. Tatsächlich bevorzuge ich Ihre Antwort.
Don Roby
@ ZacharyYoung, Entschuldigung, ich verstehe die Frage nicht. Wenn Sie meinen, warum nicht alle möglichen Elemente aus dem XML-Quelldokument übereinstimmen (und auch Textknoten), hat dieses Beispiel ein nicht übereinstimmendes Element.
Dimitre Novatchev
14

In XSL sind mehrere Vorlagenregeln integriert . Eine davon ist folgende:

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

Es gibt Text aus.

Oded
quelle
danke, ist es also spezifisch für den jeweiligen Parser oder allgemein?
InfantPro'Aravind '29.
Ich denke, seine allgemeine Regel für alle Parser ist die w3c-Spezifikation. Okay, danke :)
InfantPro'Aravind '29.
1
@infant Programmierer - es ist in der Spezifikation, wie Sie bemerkt haben ... alle XSL-Parser müssen sie implementieren.
Oded
Diese spezielle integrierte Regel entgeht speziellen XML-Zeichen , dh sie wird &amp;im Originaltext &amp;amp;in die Ausgabe umgeschrieben. Um dies zu vermeiden, fügen Sie disable-output-escaping="yes"dem <xsl:value-of>Element ein Attribut hinzu .
Jens