Knoten nach dem Kontext auswählen

(Auszug aus "XSLT Kochbuch" von Sal Mangano)

Problem

Sie wollen Knoten auswählen, die von vorhergehenden und nachfolgenden Knoten umschlossen sind.

Lösung

XSLT 1.0

Es gibt mehrere Möglichkeiten, dieses Problem in XSLT 1.0 zu lösen. Die am einfachsten zu verstehende Möglichkeit berechnet die Position der Knoten, die in jedem Schritt ausgewählt werden sollen. Hätten Sie das folgende unstrukturierte Dokument, in dem Sie die Absätze auswählen wollten, die von Überschriften eingeschlossen sind, dann könnten Sie diese Technik verwenden:

<doc>
  <heading>Struktur, Ich brauche keine Struktur</heading>
  <para>1.1</para>
  <para>1.2</para>
  <para>1.3</para>
  <para>1.4</para>
  <heading>Bekenntnisse eines Flacherdlings</heading>
  <para>2.1</para>
  <para>2.2</para>
  <para>2.3</para>
  <heading>Flache Hierarchien retten Bäume!</heading>
  <para>3.1</para>
  <para>3.2</para>
</doc>
<xsl:template match="/doc">
  <xsl:copy>
    <!-- Zuerst werden die einklammernden Elemente ausgewählt -->
    <xsl:apply-templates select="heading"/>
  </xsl:copy>
</xsl:template>
<!-- Filtern der einklammernden Elemente -->
<xsl:template match="heading">
  <!-- Es wird berechnet, wie viele der gewünschten Elemente (para) dieser Überschrift folgen -->
  <xsl:variable name="numFollowingPara" select="count(following-sibling::para)"/>
  <!-- Es wird berechnet, wie viele der gewünschten Elemente (para) der nächsten Überschrift folgen, und dieser Wert wird vom vorhergehenden Zähler abgezogen, um die Position des letzten Absatzes (para) in dieser Gruppe zu erhalten -->
  <xsl:variable name="lastParaInHeading" select="$numFollowingPara - count(following-sibling::heading[1]/following-sibling::para)"/>
  <!-- Sie können nun die gewünschten Elemente anhand ihrer Position relativ zur aktuellen Überschrift auswählen -->
  <xsl:apply-templates select="following-sibling::para[position( ) &lt;= $lastParaInHeading]"/>
</xsl:template>

XSLT 2.0

Dieses Problem ist wie geschaffen für die Anweisung for-each-group. Speziell das Attribut group-starting-with würde hier zum Einsatz kommen:

<xsl:template match="/doc">
  <xsl:copy>
    <xsl:for-each-group select="*" group-starting-with="heading">
      <!--Auswählen der para-Elemente in der Gruppe, die durch eine Überschrift eingeklammert sind -->
      <xsl:apply-templates select="current-group( )[self::para]"/>
    </xsl:for-each-group>
  </xsl:copy>
</xsl:template>

Diskussion

Das Auswählen von Knoten auf der Grundlage ihrer Position relativ zu anderen Knoten ist in dokumentenorientierten XML-Transformationen eine gebräuchliche Anforderung, bei denen die Struktur impliziert wird und nicht tatsächlich in der Hierarchie des Dokuments kodiert ist. Sicherlich, wenn jede Gruppe, die aus einer Überschrift und Absätzen besteht, in einem eigenen übergeordneten Element (zum Beispiel einem section-Element) enthalten wäre, dann wäre das Problem trivial. Dies ist ein klassischer Kompromiss zwischen einfacher Handhabung für die Dokumenterzeuger und einfacher Handhabung für die Dokumenttransformierer. Mit der Einführung von for-each-group in XSLT 2.0 wird der Kompromiss unnötig, da Sie nun mit unstrukturierten Dokumenten viel einfacher umgehen können.

Siehe auch

Das Rezept Eine XML-Hierarchie vertiefen zeigt Anwendungen dieser Technik für das Transformieren implizit strukturierter Dokumente in explizit strukturierte Dokumente. Es zeigt außerdem andere Methoden, wie das Problem in XSLT 1.0 und 2.0 angegangen werden kann.

  

<< zurück vor >>

 

 

 

Tipp der data2type-Redaktion:
Zum Thema XSLT bieten wir auch folgende Schulungen zur Vertiefung und professionellen Fortbildung an:

Copyright © 2006 O'Reilly Verlag GmbH & Co. KG
Für Ihren privaten Gebrauch dürfen Sie die Online-Version ausdrucken.
Ansonsten unterliegt dieses Kapitel aus dem Buch "XSLT Kochbuch" denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.

O'Reilly Verlag GmbH & Co. KG, Balthasarstraße 81, 50670 Köln, kommentar(at)oreilly.de