Externe Keys – Schlüssel in anderen Dokumenten

(Auszug aus "XSLT 2.0 & XPath 2.0" von Frank Bongers, Kapitel 3.)

Die document()-Funktion ist auch im Zusammenhang mit der Erstellung von Schlüsselindexlisten von Bedeutung. Es ist mit ihrer Hilfe auch möglich, externe Dokumente bei oder vor ihrer Verarbeitung mit Schlüsseln zu verse­hen. Bei der Auswertung der Schlüssel müssen wir dann aber auf den Fokus der key()-Funktion achten:

Ein Schlüssel liefert normalerweise nur solche Knoten als Ergebnis, die sich im selben Dokument wie der Current Node befinden. Um einen Schlüssel über ein anderes Dokument auszuwerten, muss also zunächst der Kontext dorthin gesetzt werden. Hierfür kann die Funktion key() optional einen zweiten Para­meter übernehmen, der ein Dokument bezeichnet. Alternativ, solange dies noch nicht implementiert ist, kann die XSLT-Funktion document() zu Hilfe genom­men werden.

Nehmen wir beispielsweise an, ein Dokument keys_buecher.xml enthalte Referenzen auf Buchtitel in der Form <buchreferenz>Mein Buchtitel</buchreferenz>, und ein anderes XML-Dokument keys_buchdaten.xml enthält eine Art bibliographische Datenbank mit Einträgen zu allen Büchern in der Form:

...
<eintrag titel="Haben oder sein">
  <wertung>Das ist ein ...</wertung>
  <zusammenfassung>Der Autor malt ein ausführliches ...</zusammenfassung>
</eintrag>
...
  

Dann könnte das Stylesheet, das die Relation zwischen den <buchref>-­Elementen in keys_buecher.xml und den Einträgen <eintrag> in buchdaten.xml auflösen soll, folgendermaßen aussehen:

<xsl:key name="ref" match="eintrag" use="@titel"/>
<xsl:template match="buchrefenz">
  <xsl:variable name="der_titel" select="."/>
  <!-- das andere Dokument wird "current": -->
  <xsl:for-each select="document('keys_buchdaten.xml')">
    <xsl:apply-templates select="key('ref',$der_titel)"/>
  </xsl:for-each>
</xsl:template>

Da ein Schlüssel nur im aktuellen Dokument ausgeführt werden kann, muss erst der Fokus in das andere Dokument gesetzt werden. Dies geschieht hier durch xsl:for-each, das mit Hilfe der document()-Funktion das gesamte externe Dokument zum Current Nodeset macht.

Der Index kann in diesem Fall eigentlich erst zum Zeitpunkt des Aufrufs der key()-Funktion erstellt werden – es existieren dank der xsl:key-Anweisung bereits ein »Bauplan« und ein Bezeichner für den Schlüssel. Zum Zeitpunkt die­ser Deklaration waren aber weder Elemente <eintrag> noch deren name-Attri­bute in Sicht. Dies tut der Funktion jedoch keinen Abbruch.

In XSLT 1.0 ist Folgendes zu beachten:

Die document()-Funktion kann nicht als Teil eines Pfadausdrucks verwendet werden, um externe Keys zu adressieren – etwa in folgender Form:

<!-- In XSLT 1.0 nicht möglich: -->
<xsl:value-of select="document('extern.xml')/key('ref',$der_titel)"/>

Die document()-Funktion gibt zwar brav den Dokumentknoten des externen Dokuments zurück, als Current Node dient aber immer noch der zum Zeitpunkt des Aufrufs von xsl:value-of gültige: Der Fokus liegt daher noch im Haupt­dokument, und der Versuch schlägt fehl. Aus diesem Grund ist der Aufruf von docu­ment() in einem Kontext erforderlich, der den Current Node wechselt.

Keys in importierten Stylesheets

Auch xsl:key-Deklarationen können zusammen mit einem externen Styles­heet importiert (und inkludiert) werden. Das Prinzip der Importpräzedenz spielt hier keine Rolle – alle Schlüssel sind gültig. Es ist nur bei der Auswer­tung mit key() darauf zu achten, dass jenes Dokument im Fokus ist, in dem sich die zu durchsuchenden Elemente befinden. Folgende, grundsätzlich gültigen Umstände kommen hier zum Tragen:

Gleichnamige Schlüssel verschmelzen.
Schlüssel können modular sein, es können also tatsächlich in jedem Fall mehrere gleichnamige Keys dekla­riert werden. Diese Schlüssel verschmelzen (merge) – dies kann man sich als Verkettung der Schlüssellisten bildhaft vorstellen.

<xsl:key name="star" match="film" use="schauspieler/name"/>
<xsl:key name="star" match="cd" use="musiker/name"/>
<xsl:key name="star" match="sport" use="sportart/name"/>

Es existiert jetzt unter dem Bezeichner star eine gemeinsame Liste mit indi­zierten <film>, <cd>- und <sport>-Elementen, die z.B. folgender­maßen »angezapft« werden könnte:

<xsl:apply-templates select="key('star', 'Tom Jones')"/>

Ergebnis ist eine Nodesequenz mit CDs und Filmen, in denen Tom Jones mitwirkt. Wäre er zusätzlich sportlich in Erscheinung getreten, so hätten wir ihn damit auch noch in diesem Bereich gefunden.

Alternative – multi-match-keys
Wenn alle diese Key-Definitionen im selben Stylesheet vorliegen (und der Wert des use-Attributs in allen Fällen identisch wäre, was hier konstruiert werden muss), dann gibt es – mit Hilfe des Union-Operators "|" auch folgende unschärfere Formulierungsmöglich­keit:

<xsl:key name="star" match="film | cd | sport" use="*/name"/>

Wenn Sie es exakter haben wollen:

<xsl:key name="star" match="film | cd | sport" use="name/parent::node()[name()='schauspieler' or name()='musiker' or name()='sportart']"/>

Lösen Sie sich nun auch noch von der Vorstellung, alle diese xsl:key-Deklara­tionen müssten im selben Stylesheet-Modul stehen, so sind Sie zum Kern der Sache vorgedrungen – dies ist nämlich nicht der Fall! Eine Addition der Listen gleich benannter Schlüssel findet immer statt, unabhängig vom Ort ihrer Deklaration. Eine »lokale« Deklaration ist gleichwertig mit einer »externen«.

   

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

Copyright © Galileo Press, Bonn 2008
Für Ihren privaten Gebrauch dürfen Sie die Online-Version ausdrucken.
Ansonsten unterliegt dieses Kapitel aus dem Buch "XSLT 2.0 & XPath 2.0 ― Das umfassende Handbuch" 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.


Galileo Press, Rheinwerkallee 4, 53227 Bonn