Bereiche

(Auszug aus "XML in a Nutshell" von Elliotte Rusty Harold & W. Scott Means)

Ein Bereich ist eine Spanne geparster Zeichendaten zwischen zwei Punkten. Er kann ein Stück wohlgeformtes XML repräsentieren, muss es aber nicht tun. Ein Bereich kann zum Beispiel das Start-Tag eines Elements einschließen, sein End-Tag aber weglassen. Bereiche eignen sich deshalb für solche Verwendungszwecke wie die Darstellung von Text, den ein Benutzer mit der Maus ausgewählt hat. Bereiche können mit Hilfe von vier Funktionen erzeugt werden, die XPointer zu XPath hinzufügt:

  • range( )
  • range-to( )
  • range-inside( )
  • string-range( )

Die Funktion range( )

Die Funktion range( ) nimmt einen XPath-Ausdruck als Argument, der eine Lokalisierungsmenge zurückgibt. Für jeden Ort in dieser Menge gibt range( ) einen Bereich zurück, der diese Stelle exakt abdeckt; d.h., der Ausgangspunkt des Bereichs ist der Punkt unmittelbar vor dem Ort, und der Endpunkt ist der Punkt unmittelbar hinter diesem Ort. Wenn es sich bei dem Ort um ein Element handelt, beginnt der Bereich direkt vor dem Start-Tag des Elements und endet direkt hinter dem End-Tag des Elements. Betrachten Sie beispielsweise diesen XPointer:

xpointer(range(//titel))

Wird er auf das Code-Beispiel Ein Roman-Dokument der Seite Punkte angewendet, wählt er den Bereich aus, der genau das einzelne Element titel umfasst. Gäbe es in diesem Dokument mehr als ein titel-Element, würde er für jedes titel-Element einen Bereich zurückgeben. Gäbe es keine titel-Elemente im Dokument, würde er keinen Bereich zurückgeben.

Betrachten Sie nun diesen XPointer:

xpointer(range(/roman/*))

Wird er auf das genannte Code-Beispiel angewendet, gibt er drei Bereiche zurück, die jeweils eines der drei Kindelemente des Wurzelelements roman umfassen.

Die Funktion range-inside( )

Die Funktion range-inside( ) nimmt einen XPath-Ausdruck als Argument, der eine Lokalisierungsmenge zurückgibt. Für jeden Ort in dieser Menge gibt er den Bereich zurück, der exakt den Inhalt dieses Orts umfasst. Mit Ausnahme eines Elementknotens ist das Ergebnis immer gleich dem Ergebnis, das range( ) zurückgibt. Bei einem Elementknoten umfasst dieser Bereich alles, was sich innerhalb des Elements befindet, nicht jedoch das Start-Tag oder das End-Tag. Wird er etwa auf das genannte Code-Beispiel angewendet, gibt xpointer(range-inside(//titel)) einen Bereich zurück, der The Wonderful Wizard of Oz, aber nicht <titel>The Wonderful Wizard of Oz</titel> umfasst. Bei Kommentar-, Verarbeitungsanweisungs-, Attribut-, Text- oder Namensraumknoten erstreckt sich der Bereich über den String-Wert des Knotens.

Die Funktion range-to( )

Die Funktion range-to( ) wird in Bezug auf einen Kontextknoten ausgewertet. Sie erhält eine Lokalisierungsmenge als Argument, die genau einen Ort liefern sollte. Die Anfangspunkte der Kontextknoten bilden die Anfangspunkte der Bereiche, die die Funktion range-to( ) zurückgibt. Der Endpunkt des Arguments gibt den Endpunkt der Bereiche vor. Wenn die Kontextknotenliste mehrere Knoten enthält, gibt die Funktion range-to( ) mehrere Bereiche zurück.

Anmerkung: Diese Funktion ist in der XPointer-Spezifikation unterbestimmt. Insbesondere bleibt unklar, was passieren soll, wenn das Argument weniger oder mehr als einen Ort enthält.

Nehmen Sie z.B. einmal an, Sie wollen einen einzelnen Bereich erzeugen, der alles zwischen <titel> und </jahr> im oben genannten Code-Beispiel abdeckt. Dieser XPointer macht das, indem er mit dem Anfangspunkt des titel-Elements beginnt und bis zum Endpunkt des jahr-Elements weitergeht:

xpointer(/titel/range-to(jahr))

Bereiche müssen nicht unbedingt wohlgeformte XML-Fragmente sein. So kann zum Beispiel das Start-Tag eines Elements einbezogen, das End-Tag aber weggelassen werden. Dieser XPointer wählt <titel>The Wonderful Wizard of Oz:

xpointer(/titel/range-to(text( )))

Er beginnt am Anfangspunkt des titel-Elements, endet jedoch am Endpunkt des Textknotenkindes des titel-Elements. Dabei wird das End-Tag weggelassen.

Die Funktion string-range( )

Die Funktion string-range( ) ist ungewöhnlich. Anstatt mit einer Lokalisierungsmenge zu arbeiten, inklusive Tags, Kommentare und Verarbeitungsanweisungen, arbeitet sie mit dem Text eines Dokuments, nachdem das Markup entfernt wurde. Tags werden mehr oder weniger ignoriert.

Die Funktion string-range( ) übernimmt als Argumente einen XPath-Ausdruck, der Orte identifiziert, und einen Teil-String, der mit den XPath-String-Werten jedes dieser Orte verglichen wird. Für jeden gefundenen nicht-überschneidenden Treffer gibt sie einen Bereich zurück, der genau den Treffer-String abdeckt. Dieser XPointer beispielsweise erzeugt Bereiche für jedes Auftreten des Worts »Wizard« in den titel-Elementen des Dokuments:

xpointer(string-range(//titel, "Wizard"))

Gibt es mehrere Treffer, werden mehrere Bereiche zurückgegeben. Dieser XPointer z.B. liefert zwei Bereiche zurück, wenn er auf das genannte Code-Beispiel angewendet wird – einen, der das W aus »Wonderful« enthält, sowie einen, der das W aus »Wizard« abdeckt:

xpointer(string-range(//titel, "W"))

Sie können auch einen Offset und eine Länge für die Funktion festlegen, so dass der String erst bei einer bestimmten Anzahl von Zeichen nach dem Anfang des Treffers beginnt und über eine festgelegte Anzahl von Zeichen reicht. Der Punkt vor dem ersten Zeichen im zu durchsuchenden String ist 1. Dieser XPointer z.B. wählt die ersten vier Zeichen nach dem Wort »Wizard« in titel-Elementen:

xpointer(string-range(//titel, "Wizard", 7, 4))

Nicht-positive Offsets wirken vom Beginn des Treffers aus rückwärts. Beispielsweise spricht dieser XPointer die ersten vier Zeichen vor dem Wort »Wizard« in titel-Elementen an:

xpointer(string-range(//titel,"Wizard", −3, 4))

Ergibt sich aus dem angegebenen Offset oder der gewählten Länge ein Bereich außerhalb des Dokuments, wird kein Bereich zurückgeliefert.

Da String-Bereiche an so ziemlich jedem Zeichen im Textinhalt eines Dokuments beginnen und enden können, bieten sie sich an, wenn es Punkte zu erreichen gilt, die nicht mit Knotengrenzen zusammenfallen. Erzeugen Sie einfach einen String-Bereich, der an der Stelle, die Sie ansprechen möchten, beginnt oder endet, und arbeiten Sie dann mit start-point() oder end-point() auf diesem Bereich. Dieser XPointer z.B. liefert den Punkt unmittelbar vor dem Wort »Wizard« im titel-Element:

xpointer(start-point(string-range(//title, "Wizard")))

Relative XPointer

Normalerweise ist ein XPointer ein Fragment-Bezeichner, der an einer URL hängt. Der Wurzelknoten des Dokuments, auf das die URL zeigt, bildet den Kontextknoten des XPointer. XPointer können allerdings auch unabhängig, ohne eine explizite URL, in XML-Dokumenten verwendet werden. Der standardmäßige Kontextknoten für solch einen XPointer ist der Wurzelknoten des Dokuments, in dem der XPointer erscheint. Mit der here()- oder mit der origin()-Funktion lässt sich aber der Kontextknoten für den XPath-Ausdruck des XPointers ändern.

here()

Die Funktion here() wird nur innerhalb von XML-Dokumenten verwendet. Sie bezieht sich auf den Knoten, der den XPointer enthält, oder, wenn dieser Knoten ein Textknoten ist, auf den Elementknoten, der diesen Textknoten enthält. Nützlich ist here() in relativen Links. Diese navigation-Elemente z.B. verweisen auf die seite-Elemente, die den Seiten, in denen sie enthalten sind, vorausgehen bzw. folgen:

<seite>
   Seiteninhalt...
   <navigation xlink:type="simple" xlink:href="#xpointer(here()/../../preceding-sibling::seite[1])">Vorherige</navigation>
   <navigation xlink:type="simple xlink:href="#xpointer(here()/../../following-sibling::seite[1])">Nächste</navigation>
</seite>

In diesen Elementen bezieht sich die Funktion here() auf die xlink:href-Attributknoten, die den XPointer enthalten. Die ersten zwei Punkte .. gehen zum Elternelement navigation. Die zweiten .. wählen dann dessen Elternelement seite, und der letzte Lokalisierungsschritt spricht das vorherige bzw. nächste seite-Element an.

origin()

Die Funktion origin() ist nützlich, wenn das Dokument von einem externen Link aus geladen wurde. Sie bezieht sich auf den Knoten, von dem aus der Benutzer die Traversierung auslöst, auch wenn es sich dabei nicht um den Knoten handelt, der den Link definiert. Sehen Sie sich beispielsweise einmal einen erweiterten Link wie diesen hier an. Er hat viele roman-Elemente, die alle Locator-Elemente mit dem gleichen Label sind:

<reihe xlink:type="extended" xmlns:xlink="http://www.w3.org/1999/xlink">
  <!-- Locator-Elemente -->
  <roman xlink:type="locator" xlink:label="oz" xlink:href="ftp://archive.org/pub/etext/etext93/wizoz10.txt">
    <titel>The Wonderful Wizard of Oz</titel>
    <jahr>1900</jahr>
  </roman>
  <roman xlink:type="locator" xlink:label="oz" xlink:href="ftp://archive.org/pub/etext/etext93/ozland10.txt">
    <titel>The Marvelous Land of Oz</titel>
    <jahr>1904</jahr>
  </roman>
  <roman xlink:type="locator" xlink:label="oz" xlink:href="ftp://archive.org/pub/etext/etext93/wizoz10.txt">
    <titel>Ozma of Oz</titel>
    <jahr>1907</jahr>
  </roman>
  <!-- und viele Elemente mehr ... -->
  <fortsetzung xlink:type="locator" xlink:label="next" xlink:href="#xpointer(origin(  )/following-sibling::roman[1])" />
  <naechster xlink:type="arc" xlink:from="oz" xlink:to="next" />
</reihe>

Das Element fortsetzung verwendet einen XPointer und die Funktion origin(), um einen Locator zu definieren, der auf den folgenden roman der Reihe zeigt. Liest der Benutzer The Wonderful Wizard of Oz, zeigt das fortsetzung-Element auf The Marvelous Land of Oz. Liest er The Marvelous Land of Oz, führt dasselbe fortsetzung-Element zu Ozma of Oz usw. Das Element naechster definiert Links von jedem roman (sie haben ja alle das Label oz) zu seiner Fortsetzung. Die Zielressource ändert sich dabei von einem Roman zum nächsten.

  

<< zurück vor >>

 

 

 

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

  


Copyright © 2005 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 "XML in a Nutshell" 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