Alex1: Schleife über Elemente + position()-Funktion

Hallo,

ich habe folgende Problemstellung:

In der ersten Schleife "<xsl:for-each select..." gehe ich über alle Gesundheitsfragen in meinem XML-Dokument und prüfe, ob das darin enthaltene Tag "NAntwort=1" ist.
Falls dies der Fall ist, soll eine Tabelle erstellt werden, die weitere Elemente des aktuellen Tags "Gesundheitsfrage" aus gibt.

Soweit funktioniert auch alles...
Mein Problem: Wie ich das erste mal auf das Tag <NAntwort>1</NAntrwort> stoße. möchte ich den Tabellenkopf mit generieren.
Mein Ansatz war der, einfach mit der Funktion position() dies innerhalb der Schleife zu lösen.
Leider liefert mir die Funktion nicht das Ergebnis innerhalb des Schleifen-Contexts sondern das globale Ergebnis der XML-Datei.

Frage: Wie kann ich innerhalb der Schleife unterscheiden, ob ich zum ersten mal auf das Element <NAntwort> mit dem Wert "1" stoße.

Anbei die Logik - bei Bedarf, maile ich auch gerne das XML-File zum besseren Verständnis...

VIELEN DANK!

Alex

<!-- START - Abfrage, ob ein oder mehrere Gesundheitsfragen mit 'ja' beantwortet wurden  -->
  <xsl:for-each select="PPersonArray/item/VersPerson/PGesundheitsdaten/PGesundheitsfragen/item/Gesundheitsfrage">
   <!-- Prüfen, ob das Tag "PGesundheitsdaten/PGesundheitsfragen/item/Gesundheitsfrage/NAntwort"=1 vorhanden ist. Wenn ja, wurden mindestens eine Gesundheitsfrage mit "ja" beantwortet. -->
   <xsl:if test="NAntwort='1'">
<!--    <fo:block keep-together="always" text-align="start">TESTAUSGABE - Es wurden Diagnosen erfasst!</fo:block> -->

<!-- ZUERST NOCH PRÜFEN, OB MAN GERADE AN POSITION 1 IST. WENN JA, TABELLENHEADER AUSGEBEN, WENN NEIN, DANN NUR ZEILEN AUSGEBEN -->
fo:block
    xsl:choose
        <xsl:when test="position()='1'">
            <fo:inline font-size="8pt" font-family="Times" font-weight="bold">Tabelle mit HEADER erstellen!</fo:inline>
        </xsl:when>
        <xsl:when test="position()>'1'">
            <fo:inline font-size="8pt" font-family="Times" font-weight="bold">Tabelle ohne HEADER erstellen!</fo:inline>
        </xsl:when>
        xsl:otherwise
            Fehler!
        </xsl:otherwise>
    </xsl:choose>
</fo:block>

  1. Hallo Alex,

    warum prüfst du nicht vorab, ob ein solches Element vorkommt
    mit <xsl:if test="...">
    und gibst im positiven Fall die Headerinformation vorab aus?

    Gruß Mia

    1. Hallo,

      das Problem ist, dass das Element immer vorkommt, nur mit verschiedenen Werten.
      Ich prüfe ja, wie Du es auch vorgeschlagen hast mit:
      <xsl:if test="NAntwort='1'">

      Die fachliche Logik wäre jetzt, nachdem ich ein solches Element zum ersten mal gefunden habe, dass ich jetzt eine Tabelle inklusive Tabellen-Header (Spaltenbezeichnungen etc) ausgeben müsste - UND wenn ich zum 2., 3. etc. mal auf das Element stoße, eben nur eine Zeile an die Tabelle anhängen muss und nicht wieder den Header mit ausgeben darf.

      Aus diesem Grund war die Funktion position() mein Ansatz. Leider funktioniert das bei mir nicht ganz so...

      Kannst Du mir hiermit irgendwie weiter helfen?

      DANKE!
      Gruß
      Alex

      Hallo Alex,

      warum prüfst du nicht vorab, ob ein solches Element vorkommt
      mit <xsl:if test="...">
      und gibst im positiven Fall die Headerinformation vorab aus?

      Gruß Mia

      1. Hallo Alex,

        ich dachte an folgende Reihenfolge:

        <xsl:if test="NAntwort='1'">
          <table>
            Ausgabe Header
            xsl:for-each... wie bisher
              Ausgabe Zeile
            </xsl:for-each>
          </table>
        </xsl:if>

        Möglicherweise habe ich dich aber auch grundsätzlich falsch verstanden.

        Gruß Mia

      2. Hallo Mia,

        vielen Dank für Deine Antwort.
        In einem weiterem Forum habe ich die Antwort für mein Problem gefunden:
        count(PPersonArray/item/NAnswer[. = 1])

        Gruß
        Alex

        Hallo Alex,

        warum prüfst du nicht vorab, ob ein solches Element vorkommt
        mit <xsl:if test="...">
        und gibst im positiven Fall die Headerinformation vorab aus?

        Gruß Mia

  2. Hallo,

    Mein Ansatz war der, einfach mit der Funktion position() dies innerhalb der Schleife zu lösen.
    Leider liefert mir die Funktion nicht das Ergebnis innerhalb des Schleifen-Contexts sondern das globale Ergebnis der XML-Datei.

    Prinzipieller Hinweis: Verabschiede Dich von der Schleifen-Denkweise. xsl:for-each ist eine Mehrfach-Verarbeitungsanweisung. Der Begriff Schleife suggeriert, dass ein Codeblock nacheinander immer wieder von oben herab durchlaufen wird. Der Code von xsl:for-each wandert aber durch die XML-Baumstruktur (die Verarbeitung erfolgt ggf. sogar parallel). "Gefuehlsmaeßig" ist das mit einer Schleife vergleichbar, technisch nicht.

    Anbei die Logik - bei Bedarf, maile ich auch gerne das XML-File zum besseren Verständnis...

    Ja bitte, das fehlt zum Verstaendnis der Logik.

    <xsl:when test="position()='1'">

    Hier faellt zumindest auf, dass ein von position() ermittelter numerischer Wert mit einem String verglichen wird. test="position()=1" passt besser (auch wenn evtl. implizit eine Typkonvertierung erfolgt).

    Vermutung: Das Problem laesst sich gaenzlich ohne xsl:for-each loesen, wenn mehrere xsl:template-Vorlagen mittels xsl:apply-templates aufgerufen werden.

    MfG, Thomas