Janine: XSL: for-each über concat?

Hallo,

ich will über folgende Quelldaten eine For-Each-Schleife, abhängig von der Sprachvariablen, legen, sodass entweder A-B-C oder D-E-F rauskommt.

<data>
	<roles_de>
		<role>A</role>
		<role>B</role>
		<role>C</role>
	</roles_de>
	<roles_en>
		<role>D</role>
		<role>E</role>
		<role>F</role>
	</roles_en>
</data>

Dieser XSL-Code funktioniert prima:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
	<xsl:template match="/">
		<allroles>
			<xsl:for-each select="/data/roles_de/role">
				<role>
					<xsl:value-of select="."/>
				</role>
			</xsl:for-each>
		</allroles>
	</xsl:template>
</xsl:stylesheet>

Wenn ich nun aber folgendes schreibe, funktioniert das for-each nicht mehr:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
	<xsl:template match="/">
		<xsl:variable name="lang">de</xsl:variable>
		<xsl:variable name="eachrole" select="concat('/data/roles_', $lang, '/role')"/>
		<roles>
			<xsl:for-each select="$eachrole">
				<roles>
					<xsl:value-of select="."/>
				</roles>
			</xsl:for-each>
		</roles>
	</xsl:template>
</xsl:stylesheet>

Die Fehlermeldung sagt, dass ein Knoten erwartet wird, das aktuelle Element allerdings vom Typ xs:string ist. Doch auch wenn ich nur einen Teil in die Variable speichere (concat('/data/roles_', $lang)) und "/role" anfüge, bekomme ich keinen Knoten.

Gibt es für mein Problem eine Lösung? Bin für Ideen und Hinweise, wo mein Denkfehler liegt, sehr dankbar!

Viele Grüße, Janine.

PS: Eine choose-Abfrage kommt nur infrage, wenn es keine bessere Alternative gibt, da beide Dateien sehr komplex sind und ich den Code ungern unnötig aufblähen möchte.

akzeptierte Antworten

  1. Hallo Janine,

    der Trick ist, das concat ist der Bedingung zu machen:

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
        <xsl:template match="/">
           <allroles>
              <xsl:for-each select="/data/*[name() = concat('roles_', $lang)]/role">
                  <role>
                       <xsl:value-of select="."/>
                  </role>
              </xsl:for-each>
          </allroles>
       </xsl:template>
    </xsl:stylesheet>
    

    Der XPath-Ausdruck in dem <code>select</code> des <code>xsl:for-each</code> nimmt über den <code>*</code> erst mal alle Unterelemente von <code>data</code>. Über das <em>Prädikat</em> den eckigen Klammern wird das ganze wieder auf die gewünschten Elemente eingeschränkt. Die XPath-Funktion <code>name()</code> liefert den Namen des aktuellen Knotens. Da das ganze in einem Prädikat steht wird das für jeden Knoten aufgerufen. Das ganze wird dann mit dem Ergebnis der <code>concat()</code>-Funktion verglichen. Wenn beide gleich sind, wird der Knoten verwendet, ansonsten nicht. Den Wert für die <code>$lang</code>-Variable musst du natürlich noch irgendwo an passender Stelle festlegen (oder als Parameter übergeben).

    Beste Grüße

    Stareagle

    1. Vielen lieben Dank Stareagle! Der Code funktioniert prima und ich habe gleich wieder einen neuen XPath-Ausdruck gelernt :) LG Janine

      1. Hallo

        Vielen lieben Dank Stareagle! Der Code funktioniert prima und ich habe gleich wieder einen neuen XPath-Ausdruck gelernt :)

        Wenn du als Fragestellerin auch für die Nachwelt hilfreich sein möchtest, bewerte doch bitte stareagles Posting als die „akzeptierte Antwort“. Damit beeinflusst du die Gewichtung in der foreneigenen (noch zu implementierenden) Suche auf positive Weise.

        Danke und tschö, Auge

        --
        Verschiedene Glocken läuteten in der Stadt, und jede von ihnen vertrat eine ganz persönliche Meinung darüber, wann es Mitternacht war. Terry Pratchett, “Wachen! Wachen!