Hallo,
Dann stell ich einfachmal sogut wie das ganze rein, wird wohl am einfachsten sein.
Ja.
So, warum du in eine Endlosschleife gefangen bleibst - du hast eingetlich gleich mehrere eingebaut - habe ich dein XSL zum Testen und Veranschaulichen verschlankt.
Wichtig, ich habe oben im XSLT ein <xsl:strip-space elements="Intervall"/> eingefügt!
<xsl:template match="value" name="Temp1">
<xsl:param name="add" select="0"/>
<xsl:variable name="pos" select="position()" />
<xsl:for-each select="descendant-or-self::value">
<po>$pos:<xsl:value-of select="$pos"/> | pos(): <xsl:value-of select="position()"/> | val:<xsl:value-of select="."/></po>
<xsl:choose>
<xsl:when test="following-sibling::value[position() = 1]">
<fspo>fs val:<xsl:value-of select="following-sibling::value"/></fspo>
<xsl:call-template name="Temp1">
<xsl:with-param name="add" select="$add+$share" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:if test="parent::Intervall/following-sibling::Intervall[position() = 1]/value[position() = 1]">
<otw>start otherwiese</otw>
<xsl:call-template name="Temp1">
<xsl:with-param name="add" select="$add+$share" />
</xsl:call-template>
</xsl:if>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:template>
Das XSL wird ausgeführt und der Template wird aufgerufen. (Ich dokumentieren hier die Schritte und die Ausgabe dazu):
Wir stehen vor dem xsl:choose, die Ausgabe ist:
<po>$pos:1 | pos(): 1 | val:100</po>
So weit normal, wir sind im:
<Intervall name="30.05.2003">
<value>100</value>
Weiter geht es in den xsl:when (da es auf der following-sibling-Achse ein 'value' gibt). Wir stehen vor dem xsl:call-template, die Ausgabe ist:
<po>$pos:1 | pos(): 1 | val:100</po>
<fspo>fs val:105</fspo>
Das ist auch noch korrekt.
Jetzt wird das Template rekursiv aufgerufen und wir stehen wieder vor dem xsl:choose und die ausgabe ist:
<po>$pos:1 | pos(): 1 | val:100</po>
<fspo>fs val:105</fspo>
<po>$pos:1 | pos(): 1 | val:100</po>
huch!?! Die ersten zwei sind vom ersten Durchgang, aber warum sid alle Werte auch beim zweiten Mal gleich?
Weil der Kontextknoten des Templates beim ersten Mal der folgende war:
<Intervall name="30.05.2003">
<value>100</value>
Und daran hat sich auch nichts geändert! Sprich, der rekursive Aufruf hat hier nicht den Kontextknoten geändert und deshalb beginnt alle immer wieder beim ersten 'Intervall' erster 'value'. Das einzige was brav erhöht wird ist der Wert vom $add.
*Zeitraffer eingeschaltet*
Der Templateaufruf im xsl:when wurde auskommentiert und die Transformation wieder losgetreten. Beim 4. Durchlauf(*) - wir stehen _jetzt_ vor dem xsl:otherwise - sieht die Ausgabe so aus :
<po>$pos:1 | pos(): 1 | val:100</po>
<fspo>fs val:105</fspo>
<po>$pos:2 | pos(): 1 | val:105</po>
<fspo>fs val:110</fspo>
<po>$pos:3 | pos(): 1 | val:110</po>
<fspo>fs val:115</fspo>
<po>$pos:4 | pos(): 1 | val:115</po>
Das ist auch klar, nach <value>115</value> gab es keinen following-sibling::value[position() = 1] mehr, also kommt xsl:otherwise zum Zug.
ad *) hier wurde "unsichtbar" rekursiv gearbeitet, denn das Template matcht "value" also wird er rekursiv für alle values im Intervall aufgerufen. Deshalb haben wir bei $pos die Position, die das aktuell bearbeitete "value" hat. Wohingegen pos() bedingt durch das for-each immer 1 ergibt.
Das führt wieder zur Feststellung, dass for-each keine Schleife ist.
Wir gehen ins xsl:otherwise rein, der Template wird wieder rekursiv aufgerufen und wir stehen wieder vor xsl:choose, die Ausgabe ist:
<po>$pos:1 | pos(): 1 | val:100</po>
<fspo>fs val:105</fspo>
<po>$pos:2 | pos(): 1 | val:105</po>
<fspo>fs val:110</fspo>
<po>$pos:3 | pos(): 1 | val:110</po>
<fspo>fs val:115</fspo>
<po>$pos:4 | pos(): 1 | val:115</po>
<-- bis dahin sind wir gekommen und weiter gehts: -->
<otw>start otherwiese</otw>
<po>$pos:1 | pos(): 1 | val:115</po>
Huch!?!
Warum ist nach dem Templateaufruf $pos und pos() beide 1?
Das ist wie beim letzen Mal, der Kontextknoten ist diesmal zwar
<Intervall name="30.05.2003">
<value>115</value>
aber weil hier - wie auch obe - das Template _durch_ seinen Namen aufgerufen wurde, hat sich der Kontextknoten nicht geändert und in diesem Kontext ist <value>115</value> der einzige Knoten und somit hat er auch position() = 1.
Wenn wir hier weiter die Transformation ausführen bleiben wir in dieser Endlosschleife vom xsl:otherweise, da <value>115</value> keinen following-sibling::value[position() = 1] hat und somit eben xsl:otherweise zum Zug kommt.
Das ist also die Geschichte deiner zwei Endlosschleifen. ;-)
Eigentlich kannst du auf den rekursiven Templateaufruf verzichten, aber ich sehe dein Problem damit, du willst, dass $add immer erhöht wird.
Also ist die alternative, dass du den Kontextknoten wechselst:
<xsl:template match="value" name="Temp1">
<xsl:param name="add" select="0"/>
<xsl:param name="knoten" select="." />
<xsl:for-each select="$knoten/descendant-or-self::value">
<xsl:choose>
<xsl:when test="following-sibling::value[position() = 1]">
<g class="Lines1">
<line x1="{$add}%" y1="{.}%" x2="{$add+$add}%" y2="{following-sibling::value[position() = 1]}%"/>
</g>
<xsl:call-template name="Temp1">
<xsl:with-param name="add" select="$add+$share"/>
<xsl:with-param name="knoten" select="following-sibling::value[position() = 1]" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:if test="parent::Intervall/following-sibling::Intervall[position() = 1]/value[position() = 1]">
<g class="Lines1">
<line x1="{$add}%" y1="{.}%" x2="{$add+2}%" y2="{parent::Intervall/following-sibling::Intervall[position() = 1]/value[position() = 1]}%"/>
</g>
<xsl:call-template name="Temp1">
<xsl:with-param name="add" select="$add+$share"/>
<xsl:with-param name="knoten" select="parent::Intervall/following-sibling::Intervall[position() = 1]/value[position() = 1]" />
</xsl:call-template>
</xsl:if>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:template>
Was du jetzt noch anschauen musst ist, dass durch
<xsl:apply-templates select="Intervall"/>
natürlich das Ganze so oft ausgeführt wir, wie viele Intervall-Elemente du in deinem XML hast.
Grüße
Thomas