kozi: XSL Template nur einmal ausführen!

Bei einer XML/XSL Transformation durchlaufe ich die Liste von Elementen. Dabei möchte ich nach einer Prüfung einer Eigenschaft, einmalig ein Template ausführen bzw. einen Tag einfügen.
Wie kann ich bei der XSL-Transformation mir merken/speichern ob ich ein Tepmlate/Tag/if-Anweisung schon mal ausgeführt habe.
Einmal initialisierte Parameter lassen sich ja anscheinend nicht mehr ändern.

Vielen Dank im Voraus.

kozi

  1. Hallo,

    Wie kann ich bei der XSL-Transformation mir merken/speichern ob ich ein Tepmlate/Tag/if-Anweisung schon mal ausgeführt habe.
    Einmal initialisierte Parameter lassen sich ja anscheinend nicht mehr ändern.

    Gar nicht*, weil ein Template für alle jene Elemente auf die es zutrifft immer neu instantiiert wird.

    * Du kannst ein rekursives Template schreiben und/oder eine bestimmte when-otherwise-Abfrage schreiben, aber ohne den betreffenden Teil aus deinem XML und XSL kann ich dir nicht wirklich weiterhelfen.

    Grüße
    Thomas

    1. <?xml version="1.0" encoding="UTF-8"?>
      <root>
      <record-element>
        <counter>1</counter>
        <type>Dokument</type>
        <permissions>0</permissions>
        [...]
      </record-element>

      <record-element>
        <counter>2</counter>
        <type>Dokument</type>
        <permissions>1</permissions>
        [...]
      </record-element>

      <record-element>
        <counter>3</counter>
        <type>Dokument</type>
        <permissions>4</permissions>
        [...]
      </record-element>

      [...]

      </root>

      Habe das XML einmal etwas gekürzt hier eingestellt.
      Mein Problem besteht darin dass ich bei jedem record-element abfragen möchte ob die permissions größer als 0 sind. Ist dies der Fall soll etwas einmalig ausgeführt werden. Für alle anderen Element nach dem ersten mit permissions größer null soll der "spezielle Teil" auch nicht mehr ausgeführt werden.

      1. Hi,

        <?xml version="1.0" encoding="UTF-8"?>
        <root>
        <record-element>
          <permissions>0</permissions>
        </record-element>
        <record-element>
          <permissions>1</permissions>
        </record-element>
        <record-element>
          <permissions>4</permissions>
        </record-element>
        </root>
        Mein Problem besteht darin dass ich bei jedem record-element abfragen möchte ob die permissions größer als 0 sind. Ist dies der Fall soll etwas einmalig ausgeführt werden. Für alle anderen Element nach dem ersten mit permissions größer null soll der "spezielle Teil" auch nicht mehr ausgeführt werden.

        Dann müßte doch sowas funktionieren (ungetestet):

        <xsl:template match="record-element[permissions > 0]">
          <xsl:if test="position = 1">
             <!-- was immer auch für das erste Element mit permissions > 0 geschehen soll -->
          </xsl:if>
        </xsl:template>

        Wie gesagt, ungetestet, kann auch noch Syntax-Fehler enthalten.

        cu,
        Andreas

        --
        Warum nennt sich Andreas hier MudGuard?
        Schreinerei Waechter
        Fachfragen per E-Mail halte ich für unverschämt und werde entsprechende E-Mails nicht beantworten. Für Fachfragen ist das Forum da.
        1. Dann müßte doch sowas funktionieren (ungetestet):

          <xsl:template match="record-element[permissions > 0]">
            <xsl:if test="position = 1">

          Wenn ich das so einfüge wird nur noch das angezeigt was ich hier reinschreibe

          </xsl:if>
          </xsl:template>

          Ich möchte das xml in html umwandeln und dabei soll einmalig ein Element markiert werden. Nämlich dass erste mit permissions größer 0.
          Es sollen also alle Element ausgegeben werden (eine art Tabelle) und wenn das erste Element mit permissions größer 0 auftaucht soll noch ein bisschen javascript in die html seite eingefügt werden.

          Nebenbei: Ist "position" ein XSL-Attribut, dass immer zu Verfügung steht?

          kozi

          1. Hi,

            Ich möchte das xml in html umwandeln und dabei soll einmalig ein Element markiert werden. Nämlich dass erste mit permissions größer 0.
            Es sollen also alle Element ausgegeben werden (eine art Tabelle) und wenn das erste Element mit permissions größer 0 auftaucht soll noch ein bisschen javascript in die html seite eingefügt werden.

            Aha - für die Rotfärbung eines record-element gilt also die Bedingung:
            permissions in diesem record-element ist größer als 0
            keines der vorherigen record-element-Geschwister hat permissions größer 0

            also
            xsl:choose
              <xsl:when test="permissions > 0 && count(preceding-sibling[permissions > 0] == 0" >
                <!-- rotfärbung und ausgabe hier -->
              </xsl:when>
              xsl:otherwise
                <!-- ausgabe ohne rotfärbung hier
              </xsl:otherwise>
            </xsl:choose>

            (die genaue Syntax zu den preceding siblings und dem count usw. mußt Du selber nachgucken, hab schon länger nichts mehr mit XSLT gemacht)

            Nebenbei: Ist "position" ein XSL-Attribut, dass immer zu Verfügung steht?

            afaik ja.
            Bezieht sich auf die Position des aktuellen Knotens im jeweiligen Knotenset.

            cu,
            Andreas

            --
            Warum nennt sich Andreas hier MudGuard?
            Schreinerei Waechter
            Fachfragen per E-Mail halte ich für unverschämt und werde entsprechende E-Mails nicht beantworten. Für Fachfragen ist das Forum da.
            1. Danke schon mal für die Hilfe. Komme schon ein bisschen weiter.

              count(preceding-sibling::*)

              Damit zählt man alle voherigen Elemente. Ich habe leider keine Ahnung wie man jetzt eine Bedingung anfügt!

              Idee? Danke.

              --
              Keine Panik, ich weiß durchaus nicht was zu tun ist! (ALF)
              1. Hi,

                Danke schon mal für die Hilfe. Komme schon ein bisschen weiter.
                count(preceding-sibling::*)
                Damit zählt man alle voherigen Elemente. Ich habe leider keine Ahnung wie man jetzt eine Bedingung anfügt!

                Schau Dir mein Beispiel nochmal an.

                cu,
                Andreas

                --
                Warum nennt sich Andreas hier MudGuard?
                Schreinerei Waechter
                Fachfragen per E-Mail halte ich für unverschämt und werde entsprechende E-Mails nicht beantworten. Für Fachfragen ist das Forum da.
                1. Schau Dir mein Beispiel nochmal an.

                  <xsl:value-of select="count(preceding-sibling[permissions > 0])"/>

                  Ich hab es mir angeschaut. Ich habe es auch ausprobiert, aber es funktioniert so nicht.

                  <xsl:value-of select="count(preceding-sibling::[permissions > 0])"/>
                    --> Fehler: Es wurde ein Knotentest erwartet, der entweder NCName:* oder QName entspricht.

                  1. Hallo,

                    siehe meine Antwort unter https://forum.selfhtml.org/?t=113957&m=724782

                    Grüße
                    Thomas

          2. Hallo,

            <xsl:if test="position = 1">

            Nebenbei: Ist "position" ein XSL-Attribut, dass immer zu Verfügung steht?

            Nein, --> position() <-- ist eine Funktion.

            Grüße
            Thomas

      2. Hallo,

        Mein Problem besteht darin dass ich bei jedem record-element abfragen möchte ob die permissions größer als 0 sind. Ist dies der Fall soll etwas einmalig ausgeführt werden. Für alle anderen Element nach dem ersten mit permissions größer null soll der "spezielle Teil" auch nicht mehr ausgeführt werden.

        Das Temlate sollte diese Anforderung erfüllen:

        <xsl:template match="record-element">
         xsl:choose
          <xsl:when test="(permissions &gt; 0) and (not(preceding-sibling::record-element[permissions &gt; 0]))">
           <!-- spezielles fuer das element -->
          </xsl:when>
          xsl:otherwise
           <!-- fuer alle anderen elemente -->
          </xsl:otherwise>
         </xsl:choose>
        </xsl:template>

        Grüße
        Thomas

        1. Hi,

          <xsl:when test="(permissions &gt; 0) and (not(preceding-sibling::record-element[permissions &gt; 0]))">

          Dann lag ich ja mit meiner Idee gar nicht soooo falsch. Ok, not statt count == 0  dürfte etwas effektiver sein, insbes. wenn es viele Elemente gibt, da bei not ausreicht, wenn eins die Bedingung nicht erfüllt und dann die anderen gar nicht mehr angeguckt werden müssen ...

          Muß das > wirklich als &gt; geschrieben werden?

          cu,
          Andreas

          --
          Warum nennt sich Andreas hier MudGuard?
          Schreinerei Waechter
          Fachfragen per E-Mail halte ich für unverschämt und werde entsprechende E-Mails nicht beantworten. Für Fachfragen ist das Forum da.
          1. Hallo,

            Muß das > wirklich als &gt; geschrieben werden?

            Müssen nicht, aber ich finde es besser so. ;-)

            Grüße
            Thomas

          2. Vielen Dank an euch!

            gruß kozi

    2. Hi,

      Wie kann ich bei der XSL-Transformation mir merken/speichern ob ich ein Tepmlate/Tag/if-Anweisung schon mal ausgeführt habe.
      Einmal initialisierte Parameter lassen sich ja anscheinend nicht mehr ändern.
      Gar nicht*, weil ein Template für alle jene Elemente auf die es zutrifft immer neu instantiiert wird.

      Wenn ich das richtig in Erinnerung habe, ist es doch sogar so, daß bei

      <root>
        <elem>bla</elem>
        <elem>blubb</elem>
      </root>

      mit
      <xsl:template match="elem">
        <xsl:value-of select="."/>
      </xsl:template>

      noch nichtmal festgelegt ist, in welcher Reihenfolge die Template-Aufrufe durchgeführt werden *) - nur die Ausgabe der Ergebnisse muß in der Reihenfolge, in der die elem-Teile im Dokument stehen, erfolgen.
      Dann wäre "wurde schon mal ausgeführt" sowieso nicht definiert.

      Oder hab ich das falsch in Erinnerung?

      *) auch wenn die meisten XSL-Transformatoren wohl die Dokument-Reihenfolge benutzen.

      cu,
      Andreas

      --
      Warum nennt sich Andreas hier MudGuard?
      Schreinerei Waechter
      Fachfragen per E-Mail halte ich für unverschämt und werde entsprechende E-Mails nicht beantworten. Für Fachfragen ist das Forum da.
      1. Hallo Andreas,

        Gar nicht*, weil ein Template für alle jene Elemente auf die es zutrifft immer neu instantiiert wird.

        Wenn ich das richtig in Erinnerung habe, ist es doch sogar so, daß [...]
        noch nichtmal festgelegt ist, in welcher Reihenfolge die Template-Aufrufe durchgeführt werden *) - nur die Ausgabe der Ergebnisse muß in der Reihenfolge, in der die elem-Teile im Dokument stehen, erfolgen.
        Dann wäre "wurde schon mal ausgeführt" sowieso nicht definiert.
        *) auch wenn die meisten XSL-Transformatoren wohl die Dokument-Reihenfolge benutzen.

        Das ist absolut korrekt.
        Die Instantiierung eines Templates ist kein sequenzieller Prozess - das ist eine der Effekte vom XSLT als seiteneffektfreie Sprache - und die das Template kann in unterschiedlicher Ordnung oder auch parallel ausgeführt werden. Und wie du sagst, nur die Reihenfolge in der Ausgabe muss dann stimmen.

        Grüße
        Thomas