Variablenzuweisung in XSL?
Christoph W
- xsl
0 fjh0 Thomas J.S.
hallo,
ich frage mich ob man mit XSL einmal definierte Variablen veraendern kann, ohne dass die vorher darin sich befindenden Werte geloescht werden...
Hintergrund: ich will eine Art Liste definieren, die die ID Attribute der Elemente enthaelt
<xsl:variable name="idlist"><xsl:value-of select="concat($idlist, ':', @xmi.id, ':')"/></xsl:variable>
eine derartige Definition funktioniert (zumindest bei mir mit saxon) nicht, da die Variable $idlist bei jedem durchlauf resettet wird...
Vorschlaege, wie ich dieses Problem loesen koennte (sofern ueberhaupt loesbar, waere aber ein ziemliches Armutszeugnis fuer XSL, wenn man keinerlei Variablenzuweisungen machen kann...)?
greetz
Hallo,
ich frage mich ob man mit XSL einmal definierte Variablen veraendern kann, ohne dass die vorher darin sich befindenden Werte geloescht werden...
XSLT ist eine Sprache ohne Nebeneffekte, d.h. Du kannst den Wert, den Du einer Variable einmal zugewiesen hast, nicht mehr ändern.
Ein Workaround ist ein rekursiver Template-Rule-Aufruf. Bei jedem Durchlauf wird die gerade ausgeführte Template-Rule erneut aufgerufen. Als Parameter erhält sie den Wert, den die Variable beim letzten Aufruf hatte usw. Folgendes Stylesheet implementiert einen einfachen Zähler:
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- aufruf der schleife -->
<xsl:template match="/">
<xsl:call-template name="fori">
<xsl:with-param name="myCounter" select="0"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="fori">
<xsl:param name="myCounter"/>
<!-- hochzaehlen für naechsten durchlauf -->
<xsl:variable name="mbCounter" select="$myCounter + 1"/>
<!-- ausgabe -->
<xsl:number value="$mbCounter" format="1 "/>
<xsl:if test="$mbCounter < 5"><!-- bis 5 -->
<!-- naechster rekursiver aufruf mit $myCounter+1 -->
<xsl:call-template name="fori">
<xsl:with-param name="myCounter" select="$mbCounter"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
Hintergrund: ich will eine Art Liste definieren, die die ID Attribute der Elemente enthaelt
<xsl:variable name="idlist"><xsl:value-of select="concat($idlist, ':', @xmi.id, ':')"/></xsl:variable>
eine derartige Definition funktioniert (zumindest bei mir mit saxon) nicht, da die Variable $idlist bei jedem durchlauf resettet wird...
HM, ohne nähere Angaben schwierig zu erraten, was Du eigentlich genau machen möchtest und wie die Randbedingungen sind. Wenn du jedoch lediglich alle Werte der xmi.id-Attribute in eine Variable einlesen willst und die einzelnen Werte durch : trennen willst, benötigst Du dazu kein Update einer Variable. Du kannst es dann mit einem Variablenwert machen, der sich aus einem Baum zusammensetzt. Auch hierfür ein kurzes Beispiel:
<?xml version="1.0" encoding="iso-8859-1"?>
<?xml-stylesheet href="../xsl/xsl56.xsl" type="text/xsl"?>
<wurzelelement>
<element id="1">inhalt 1</element>
<element id="2">inhalt 2</element>
<element id="3">inhalt 3</element>
<element id="4">inhalt 4</element>
<abstract>A comprehensive guide to the XSLT and XPath recommendations published by the World Wide Web Consortium on 16 November 1999</abstract>
</wurzelelement>
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" encoding="iso-8859-1" indent="yes"/>
<xsl:variable name="idlist">
<xsl:call-template name="format-ids">
<xsl:with-param name="ids" select="/wurzelelement/element/@id"/>
</xsl:call-template>
</xsl:variable>
<xsl:template name="format-ids">
<xsl:param name="ids"/>
<xsl:for-each select="$ids">
<xsl:value-of select="."/>:
</xsl:for-each>
</xsl:template>
<xsl:template match="/">
<html>
<head><title>Tree-Variablen</title></head>
<body>
<p>idlist:</p>
<p><xsl:value-of select="$idlist"/></p>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Vorschlaege, wie ich dieses Problem loesen koennte (sofern ueberhaupt loesbar, waere aber ein ziemliches Armutszeugnis fuer XSL, wenn man keinerlei Variablenzuweisungen machen kann...)?
Nein kein Armutszeugnis, sondern Prinzip.
greetz
Hallo,
Hintergrund: ich will eine Art Liste definieren, die die ID Attribute der Elemente enthaelt
<xsl:variable name="idlist"><xsl:value-of select="concat($idlist, ':', @xmi.id, ':')"/></xsl:variable>
Zusätzlich zum dem was Franz schon gesagt hat; du kannst es auch mit xsl:key machen.
<xsl:key name="idliste" match="deinElement" use="@xmi.id">
dieser key enthält nun alle <deinElement> Elemente mit einem xmi.id Attribut.
Wenn du jetzt ein Element mit einem Attributwert myID1 suchst/brauchst, kannst du das so machen:
z.B. <xsl:apply-templates select="key('idliste', 'myID1')" />
oder was anderes damit anstellen, key() kannst du immer dort verwenden wo du einen XPath-Ausdruck verwenden kannst.
waere aber ein ziemliches Armutszeugnis fuer XSL, wenn man keinerlei Variablenzuweisungen machen kann...)?
Das kannst du.
Grüße
Thomas