Hallo,
for-each keine Schleife ist.
Interessante Sichtweise, könntest du sie begründen. Damit es nicht langweilig wird, nehme ich schon mal den gegenteiligen Standpunkt ein, behaupte also, for-each ist sehr wohl eine Schleife :-)
Ich könnte jetzt zwei Dinge sagen:
- *RTFA(rchiv)!*
- Begründe doch deinen Einwand. Du wirst doch Argumente dafür haben, warum es in einer for-each "schleift" und "loopt".
Aber gut.
Es gibt paar grundlegende Sachen, die man dazu wissen muss:
-
die for-each Anweisung selektiert eine Kontenmenge und führt _dieselbe_ Verarbeitung für jeden der Konten durch.
(so weit ist noch alles klar denke ich) -
for-each ist auch ein Template. Sie instanziiert seinen Inhalt (also das Template das sie enthält) _einmal für jeden selektierten Knoten_. Der aktuell Konten (current node) ist dabei immer derjenige der gerade abgearbeitet wird.
-
In XSLT sind Variablen nicht update-fähig. D.h. der Wert einer Variable kann nicht zur Laufzeit verändert werden.
-
XSLT ist eine funktionale Sprache, sie hat keine Seiteneffekte (so ein Seiteneffekt wäre Variablen zur Laufzeit zu ändern). Als funktionale Sprache arbeitet XSLT inkrementell (und das geht nur ohne Seiteneffekte), d.h. mehrere kleinere unabhängige "Funktionen", bei denen jeder ein Stück aus der Eingabe in Relation zu einer Stück aus der Ausgabe stellt. Deshalb gibt es in XSLT auch keine Zuweisungsangaben*
Setzt man das zusammen ergibt sich folgendes Bild:
In der konventionellen Programmierung werden Variablen oft dazu benutzt, um den Stand über den aktuellen "Ort" in der Schleife zu speichern.
Bsp:
iterator = liste.holeIterator();
while (iterator.hatMehrElemente()) {
elment = iterator.holeNaechtesElement();
elment.machEtwas();
}
* Die Zuweisungsangabe ist "elment = iterator.holeNaechtesElement();", diese Angabe weist jedes Mal der Variable "element" einen neuen Wert zu.
So etwas in XSLT ist aber nicht möglich:
<xsl:variable name="iterator" select="count(liste/*)" />
<xsl:for-each select="liste/*">
<xsl:if test="$iterator > 0">
.....
<xsl:variable name="iterator" select="$iterator - 1" />
</xsl:if>
</xsl:for-each>
Das funktioniert nicht.
Auch andere Arten von Variable-Updates würde nicht funktionieren:
<xsl:variable name="x" select="0" />
<xsl:for-each select="liste/*">
<xsl:value-of select="x + 1"/>
</xsl:for-each>
Die Ausgabe wäre immer "1", weil das Template in for-each jedes Mal neu für das aktuelle Element instantiiert wird und somit ist der Ausgangswert für "x" immer Null. Die nächste Iterationsrunde weiß nichts von der vorherigen.
Daher: es schleift und loopt nichts im for-each.
Will man eine "klassische Schleife" haben, greift man zur Rekursion.
Grüße
Thomas