Seraphina: XSL ancestor?

Hallo, ich bekomme bei diesem Problem gerade einen Knoten im Kopf und hoffe, ihr könnt mir weiterhelfen!

Die Ausgangsdatei sieht folgendermaßen aus:

<?xml version="1.0" encoding="UTF-8"?>
<test>
	<title>a</title>
	<foo/>
	<foo obstitle="b"/>
	<foo/>
	<foo/>
	<foo obstitle="c"/>
	<foo/>
</test>

Und die Zieldatei soll so aussehen:

<test>
	<foo>a</foo>
	<foo>a</foo>
	<foo>b</foo>
	<foo>b</foo>
	<foo>b</foo>
	<foo>c</foo>
</test>

Das heißt, der Titel "a" soll so lange verwendet werden, bis das Attribut "obstitle" kommt, welches für alle weiteren Geschwister gilt - und das so lange, bis ein neues "obstitle" kommt. Dabei soll das Element, das den obsolenten Titel definiert, selbst noch den vorherigen Titel bekommen. Ist das soweit verständlich?

Ich habe dabei versucht, mit dem XPath "ancestor" auf eine Lösung zu kommen, doch entweder wende ich das falsch an oder habe einen Fehler in meiner choose-Abfrage... Bin für einen kritischen Blick und Hinweise dankbar!

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
	<xsl:template name="test">
		<test>
			<xsl:for-each select="//foo">
				<foo>
					<xsl:choose>
						<xsl:when test="ancestor::obstitle">
							<xsl:value-of select="ancestor::obstitle"/>
						</xsl:when>
						<xsl:otherwise>
							<xsl:value-of select="title"/>
						</xsl:otherwise>
					</xsl:choose>
				</foo>
			</xsl:for-each>
		</test>
	</xsl:template>
</xsl:stylesheet>

LG Seraphina

akzeptierte Antworten

  1. Hallo Seraphina,

    Ich habe dabei versucht, mit dem XPath "ancestor" auf eine Lösung zu kommen, doch entweder wende ich das falsch an oder habe einen Fehler in meiner choose-Abfrage... Bin für einen kritischen Blick und Hinweise dankbar!

    ancestor ist die Vorfahren-Achse, hier sollte die Vorgänger-Geschwister-Achse preceding-sibling zielführend sein. Zudem wird hier das Element obstitle und nicht das Attribut @obstitle angesprochen.

    Damit entsteht das gesuchte Ergebnis:

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
      <xsl:template match="test">
        <test>
          <xsl:for-each select="foo">
            <xsl:variable name="tit" select="preceding-sibling::title"/>
            <xsl:variable name="obs" select="preceding-sibling::foo[@obstitle][1]/@obstitle"/>
            <foo>
              <xsl:choose>
                <xsl:when test="$obs != ''">
                  <xsl:value-of select="$obs"/>
                </xsl:when>
                <xsl:otherwise>
                  <xsl:value-of select="$tit"/>
                </xsl:otherwise>
              </xsl:choose>
            </foo>
          </xsl:for-each>
        </test>
      </xsl:template>
    </xsl:stylesheet>
    

    Falls title nochmals vorkommen kann, ist noch etwas Feintuning nötig.

    Grüße, Thomas

    1. Hallo Thomas, vielen lieben Dank! Dein Template funktioniert prima :) Jetzt muss ich es nur noch verstehen und daraus lernen, damit ich das beim nächsten Mal selbst hinbekomme. LG Seraphina