2009-08-27 7 views
6

Ich habe einen Block von XSLT, die mehrmals während einer Transformation angewendet werden kann. Aber ich will es eigentlich nur beim ersten Mal laufen lassen, es sollte alle untergeordneten Zeiten übersprungen werden. Wie mache ich das?In XSLT, kann ich eine Vorlage nur einmal ausführen

Als Beispiel ist dies die Art von Sache, die ich tun möchte: Im Sheet ich eine globale Variable definieren:

<xsl:variable name="run_once" select="0"/> 

Dann eine Vorlage Ich habe das mehrmals aufgerufen wird:

<xsl:template name="some_template"> 
    <xsl:if test="$run_once != 1"> 
     <xsl:variable name="run_once" select="1"/> 
     <xsl:text>THIS TEXT SHOULD APPEAR ONLY ONCE</xsl:text> 
    </xsl:if> 
</xsl:template> 

Dies funktioniert natürlich nicht, weil Variablen nicht geändert werden können, nur überlastet. Wenn also die Datei some_template beendet wird, ist $ run_once wieder 0 und der Text wird jedes Mal angewendet, wenn die Vorlage aufgerufen wird. Gibt es einen Typ von Ifdef-Funktionalität oder ein anderes globales Objekt, das ich einstellen kann?

Wenn Sie daran interessiert sind, warum ich dies tun wollen, ist eine ausführlichere Erklärung für mein Problem und die Lösung, die ich verwendet:

  • Meine Eingabe von Daten in XML-Rohdaten, mein Ausgang ein Bericht im WordML-Format.
  • Im Eingang habe ich eine Reihe von Knoten (mit dem Namen theNode). Einige, aber nicht alle dieser Knoten müssen in der Ausgabe angezeigt werden. Der Knoten sollte nur angezeigt werden, wenn die XPATH hairyLogic wahr ist (haarigeLogik ist offensichtlich lang und komplex).
  • theNode haben auch eine Typ (in ein Unterknoten gespeichert). In der Eingabe werden alle theNode's des gleichen Typs immer zusammen gruppiert. In der Ausgabe sollten alle Knoten des gleichen Typs unter einer spezifischen Überschrift für diesen Typ gruppiert werden (dort sollte nur eine Überschrift für jeden Typ sein).

Dies ist die Lösung, die ich am Ende mit:

... 
<xsl:apply-templates select="theNode[hairyLogic]"/> 
... 

<xsl:template match="theNode"> 
    <xsl:if test="count(preceding-sibling::theNode[type = current()/type and hairyLogic])=0"> 
     <xsl:choose> 
      <xsl:when test="type = 'TYPE1a' or type = 'TYPE1b'"> 
       <xsl:call-template name="TYPE1Heading"/> 
      </xsl:when> 
      <xsl:when test="type = 'TYPE2'"> 
       <xsl:call-template name="TYPE2Heading"/> 
      </xsl:when> 
     </xsl:choose> 
    </xsl:if> 
    ... 
</xsl:template> 

Ich wählte benannten Vorlagen für die Überschriften zu verwenden, weil sie grundlegende WordML enthalten, die in der Eingabe zu Daten abhängen XML nicht.

Ich mag diese Lösung nicht, weil hairyLogic wiederholt wird und die if-Anweisung verschlungen und schwer zu lesen ist. Vielleicht haben Sie eine bessere Lösung, die keine veränderbaren Variablen benötigt?

Antwort

2

Ich würde empfehlen, Vorlagen über benannte Vorlagen zu verwenden, weil es mehr ist, nun, was ist das XSLT-Äquivalent von pythonic? Xslt-y?Ich denke, Sie werden feststellen, dass Sie Probleme leichter in dieser Verarbeitungsmethode lösen können.

Wenn Sie aufgrund einer unbekannten Anforderung auf der Verwendung benannter Vorlagen bestehen, stellen Sie möglicherweise fest, dass Sie Ihre Logik vereinfachen, wenn Sie Ihre Logik so umgestalten, dass die erste Instanz leichter erkannt wird.

Können Sie klären, warum Sie nicht feststellen können, wann die erste Instanz benötigt wird? Wir können Ihnen wahrscheinlich dabei helfen, einen XPath-Ausdruck zu erstellen, mit dem Sie das wollen, was Sie wollen. Z.B.

<xsl:template name="some_template"> 
    <xsl:variable name="EXPRESSION" select=".[somelogic='true']"/> 
    <xsl:if test="$EXPRESSION"> 
     <xsl:text>THIS TEXT SHOULD APPEAR ONLY ONCE</xsl:text> 
    </xsl:if> 
</xsl:template> 

Da XSLT ist deterministisch - ein Effekt des Seins voll funktionsfähig wie Greg es ausdrückte - (es sei denn, Sie seltsame Erweiterung Sachen tun) Sie entscheiden können, wenn das erste Mal durch die Anwendung Logik an den Eingang geeignet ist. Außerdem haben Sie Zugriff auf den Kontextknoten in der Vorlage, damit Sie wissen, von wo aus er aufgerufen wird.

+0

"Was ist das XSLT-Äquivalent von Pythonic? Xslt-y?" - Es ist "deklarativ" –

+0

Ja, ich habe Einschränkungen, die ich nicht vollständig detailliert habe (hinzugefügt, um die Frage, wenn Sie daran interessiert sind). Ich habe das Problem so gelöst, wie du es beschrieben hast. Ich mag es nicht, weil "Somelogisch" lang, unordentlich ist und jetzt mehrere Male wiederholt wird. Es wäre nicht so schlimm, wenn ich diktieren könnte, wenn XPATH-Code geparst wird, wie ich es in anderen funktionalen Sprachen kann. Dann könnte ich das schlechte Bit von "Somelogic" in einer Variablen speichern und es bei Bedarf in meine Ausdrücke einfügen. – oillio

2

Da XSLT eine rein funktionale Sprache ist, gibt es keine globale Variablen, die Sie festlegen können.

Sie müssen stattdessen die Umstände wählen, unter denen Sie Ihre some_template Vorlage aufrufen. Wenn Sie es nur einmal anrufen möchten, führen Sie nur einen Anruf an.

Verwandte Themen