Die Adressierung

Unter der Adressierung ist eine Formulierung zu verstehen, die es dem Prozessor erlaubt, Knoten oder Knotenmengen anzusteuern bzw. diese zu selektieren. Solche Adressierungen werden auch Lokalisierungspfade genannt und können in unterschiedlichen Erscheinungsformen auftreten:

  • in verkürzter oder ausführlicher Schreibweise,
  • als relative oder absolute Lokalisierungspfade.

Verkürzte oder ausführliche Schreibweise

Für die hier bereits genannten Knoten und Achsen existiert eine verkürzte und eine ausführliche Schreibweise. Beide Schreibweisen werden in der Praxis gemischt verwendet. Die verkürzte ist immer dann üblich, wenn es sich um sehr häufig angesteuerte Knoten der Achsen handelt, während die ausführliche bei den selteneren Knoten und Achsen üblich ist. In den folgenden Abschnitten werde ich die ausführliche Schreibweise darstellen und dazu die verkürzte, wenn sie häufig verwendet wird. Im Referenzteil finden sich alle ausführlichen und verkürzten Schreibweisen mit einer kurzen Erläuterung.

Ein Beispiel in ausführlicher Notation:

/child::buch/child::autor/child::name/attribut::nachname

in verkürzter Notation:

/buch/autor/name/@nachname

In der verkürzten Notation wird auf die Achsenbezeichnung child:: verzichtet und der Attributknoten mit dem Zeichen @ bezeichnet. Hierzu in den späteren Beispielen mehr.

Verkürzte Schreibweisen

Ausführliche SchreibweiseVerkürzte Schreibweise
child:: "Default"-Achse,
kann weggelassen werden
attribute:: @
descendant-or-self::node()/ //
self::node() .
parent::node() ..

Relative und absolute Pfade

Es ist möglich, einen Lokalisierungspfad relativ oder absolut (vom Wurzelelement ausgehend) zu schreiben. Genau genommen gehen die absoluten Lokalisierungspfade vom Wurzelknoten aus – das ist der Knoten, der direkt oberhalb des Wurzelelements liegt. Würde man diese Unterscheidung nicht machen und lediglich vom Wurzelelement ausgehen, dann könnte man beispielsweise Prozessinstruktionen oder Kommentare, die außerhalb des Wurzelelements liegen, nicht adressieren können.
Die Lokalisierungspfade setzen sich aus mehreren Einzelschritten zusammen, die durchSchrägstriche voneinander getrennt werden.

Ein Beispiel:

/child::EUROPA/child::LAND/child::NAME

Relative und absolute Pfade

Der Wurzelknoten wird mit dem ersten Schrägstrich angegeben. Von dort aus wird das Wurzelelement <EUROPA> selektiert, welches ein Kindelement <LAND>, das wiederum ein Kindelement <NAME> haben muss, damit es zu einem Treffer kommt. Die Achsen werden unter Angabe des Namens gefolgt von zwei Doppelpunkten angegeben. Im Falle von child:: kann die Achsenangabe auch entfallen. Folglich ist der Pfad /EUROPA/LAND/NAME gleichwertig (in verkürzter Schreibweise). Relative Pfade hingegen erlauben die Suche nach einer festgelegten Kombination im gesamten Dokument. Sie werden mit doppelten Schrägstrichen eingeleitet.

Beispiel:

//child::LAND/child::NAME

Der Prozessor sucht im gesamten Dokument nach dem Element <LAND> und dessen Kind-element <NAME>. Ob es also zu einem Treffer kommt, hängt nun davon ab, ob dieseKombination im Dokument vorkommt. Die Beschreibung für relative Pfade ist hier unvollständig! Wir verweisen auf die Spezial-Literatur zu XPath.

XPath-Beispiele im Kontext eines XSLT-Stylesheets

Unsere Übungsinstanz (Europa.xml):

        <?xml version="1.0" encoding="UTF-8"?>
        <EUROPA>
            <LAND>
                <NAME>Deutschland</NAME>
                <EINWOHNERZAHL EINHEIT="Millionen">82.4</EINWOHNERZAHL>
                <HAUPTSTADT>Berlin</HAUPTSTADT>
                <KFZ-KENNZEICHEN>D</KFZ-KENNZEICHEN>
                <TEL-VORWAHL>0049</TEL-VORWAHL>
 
            </LAND>
            <LAND>
                <NAME>Frankreich</NAME>
                <EINWOHNERZAHL EINHEIT="Millionen">58.5</EINWOHNERZAHL>
                <HAUPTSTADT>Paris</HAUPTSTADT>
                <KFZ-KENNZEICHEN>F</KFZ-KENNZEICHEN>
                <TEL-VORWAHL>0033</TEL-VORWAHL>
            </LAND>
            <LAND>
                <NAME>Spanien</NAME>
                <EINWOHNERZAHL EINHEIT="Millionen">39.4</EINWOHNERZAHL>
                <HAUPTSTADT>Madrid</HAUPTSTADT>
                <KFZ-KENNZEICHEN>E</KFZ-KENNZEICHEN>
                <TEL-VORWAHL>0034</TEL-VORWAHL>
            </LAND>
        </EUROPA>
 

Es folgt ein XSLT-Beispiel mit XPath-Adressierungen:

        <?xml version="1.0" encoding="UTF-8"?>
        <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/
            Transform">
            <xsl:template match="/">  
                <html>
                    <title></title>
                    <body>
                        <h3>
                            <xsl:apply-templates/>
                        </h3>
                    </body>
                </html>
            </xsl:template>
            <xsl:template match="EUROPA">                       
            <xsl:if test="LAND/NAME">                      
                    TREFFER : /EUROPA/LAND/NAME
                    <br/>
                </xsl:if>
                <xsl:if test="LAND/EINWOHNERZAHL">           
                    TREFFER : /EUROPA/LAND/EINWOHNERZAHL
                    <br/>
                </xsl:if>
                <xsl:if test="LAND/HAUPTSTADT">          
                    TREFFER : /EUROPA/LAND/HAUPTSTADT
                    <br/>
                </xsl:if>
                <xsl:if test="child::EINWOHNERZAHL">             
                    TREFFER : /EUROPA/EINWOHNERZAHL
                    <br/>
                </xsl:if>
                <xsl:if test="descendant::EINWOHNERZAHL">        
                    TREFFER : /EUROPA/descendant::EINWOHNERZAHL
                    <br/>
                </xsl:if>
                <xsl:if test="LAND/NAME/following-sibling::EINWOHNERZAHL">
                    TREFFER : /EUROPA/LAND/NAME/following-sibling::EINWOHNERZAHL
                    <br/><br/><br/><br/>
                </xsl:if>
                <xsl:if test="LAND/NAME/following-sibling::EINWOHNERZAHL/    
                    parent::LAND/descendant::HAUPTSTADT">
                    TREFFER : /EUROPA/LAND/NAME/following-sibling::EINWOHNERZAHL/
                    parent::LAND/descendant::HAUPTSTADT
                    <br/><br/><br/><br/>
                </xsl:if>
                <xsl:apply-templates/> </xsl:template> <xsl:template match="LAND"> 
                    <xsl:if test="HAUPTSTADT">  TREFFER : /EUROPA/LAND/HAUPTSTADT
                        <br/>
                    </xsl:if> <xsl:if test="parent::EUROPA">  TREFFER : /EUROPA/LAND/parent::EUROPA
                        <br/>
                    </xsl:if>
                </xsl:template>
        </xsl:stylesheet>
 

Zeile 04: Das Zeichen /bezeichnet den Wurzelknoten.

Zeile 14: Das Element <xsl:template> bezieht sich auf das Wurzelelement <EUROPA>. Für die nun nachfolgenden <xsl:if>-Elemente des Templates ist dies der Kontextknoten. Das heißt, dass alle nun folgenden Lokalisierungspfade von diesem Ausgangspunkt ausgehen. Im ersten Beispiel also LAND/NAME. Da es ein Kindelement <LAND> von <EUROPA> gibt, das selbst ein Kindelement <NAME> hat, werden die Anweisungen, die sich innerhalb des <xsl:if> Elements befinden, ausgeführt. Es erscheint in der Anzeige der absolute Pfad: /EUROPA/ LAND/NAME.

Zeile 19: Ein weiteres Beispiel zur Demonstration der Position des Kontextknotens.

Zeile 23: Ein weiteres Beispiel zur Demonstration der Position des Kontextknotens.

Zeile 27: Hier erfolgt keine Ausgabe, weil es vom Kontextknoten <EUROPA> aus betrachtet kein Kindelement namens <EINWOHNERZAHL> gibt. Hier hätte es auch genügt, EINWOHNERZAHL zu schreiben, da nach der Konvention dieses stellvertretend für child::EINWOHNERZAHL stehen kann.

Zeile 30: Hier erfolgt wieder eine Ausgabe, da es einen descendant(Nachkommen) <EINWOHNERZAHL> von <EUROPA> aus gibt.

Zeile 35: An dieser Stelle sucht der Prozessor nach einem nachfolgenden Geschwisterelement (following-sibling::)<EINWOHNERZAHL>von <NAME>, das ebenfalls <LAND> als Elternelement hat. Da das Element <EINWOHNERZAHL> tatsächlich nach <NAME> steht, erfolgt dieAusgabe.

Zeile 39: Das hier gezeigte Suchmuster soll zeigen, dass die Komplexität beliebig zu erhöhen ist.Hier wird nach einem Element gesucht, das ein Kindelement mit dem Namen <LAND> vom Kontextknoten <EUROPA> ist. Dieses soll wiederum ein Kindelement <NAME> enthalten, welches ein nachfolgendes Geschwisterelement <EINWOHNERZAHL> hat. Bis hierher entspricht diese Abfrage der vorangegangenen und wir wissen, dass diese zutrifft. DasElement <EINWOHNERZAHL>soll nun als Elternelement das Element <LAND> haben, welches einen Nachfahren <HAUPTSTADT> haben soll. Wie in der Ausgabe zu sehen, treffen alle dieseVoraussetzungen zu.

Zeile 45: Das neue Template sorgt an dieser Stelle dafür, dass der Kontextknoten ein anderer ist.Nun beziehen sich die Suchmuster innerhalb des Templates auf <LAND>. An dieser Stelle wird gefragt, ob das Element <LAND> ein Kindelement <HAUPTSTADT> hat.

Zeile 48: Hier wird nach einem Elternelement <EUROPA> des Kontextknotens <LAND> gesucht.

Wir erhalten nun folgendes Ergebnis:

        <html>
        <title></title>
        <body>
            <h3> 
                TREFFER : /EUROPA/LAND/NAME 
                <br/> 
                TREFFER : /EUROPA/LAND/EINWOHNERZAHL
                <br/>
                TREFFER : /EUROPA/LAND/HAUPTSTADT 
                <br/> 
                TREFFER : /EUROPA/descendant::EINWOHNERZAHL
                <br/> 
                TREFFER : /EUROPA/LAND/NAME/following-sibling::EINWOHNERZAHL
                <br/><br/><br/><br/> TREFFER : /EUROPA/LAND/NAME/following-sibling::EINWOHNERZAHL/
                parent::LAND/descendant::HAUPTSTADT 
                <br/><br/><br/><br/> 
                TREFFER : /EUROPA/LAND/HAUPTSTADT 
                <br/> 
                TREFFER : /EUROPA/LAND/parent::EUROPA 
                <br/> 
                TREFFER : /EUROPA/LAND/HAUPTSTADT 
                <br/> 
                TREFFER : /EUROPA/LAND/parent::EUROPA 
                <br/> 
                TREFFER : /EUROPA/LAND/HAUPTSTADT 
                <br/> 
                TREFFER : /EUROPA/LAND/parent::EUROPA 
                <br/>
            </h3>
        </body>
        </html>

Formatierer-Ansicht

In bestimmten Satzgestaltungen (z.B. in diesem Buch) möchte man allgemein die ersteZeile eines Absatzes um einen bestimmten Wert einrücken, dies aber nicht nach direktvorangehenden Überschriften, die am linken Satzspiegelrand angeschlagen sind. Das erstehier folgende Template regelt die Gestaltung für die Absätze allgemein, das zweite gilt füralle Absätze, die einer Überschrift direkt folgen. Das Absatzelement heißt <para>, dasÜberschriftenelement <title>.

        <xsl:template match="para">
            <fo:block text-indent="6mm"><xsl:apply-templates/></fo:block>
        </xsl:template>
        <xsl:template match="para[preceding-sibling::*[1][self::title]]">
            <fo:block text-indent="0mm"><xsl:apply-templates/></fo:block>
            </xsl:template>

Zur weiteren Einübung hier eine kleine Sammlung von Pfaden:

  • child::EUROPA gibt die Kindelemente vom Element <EUROPA> zurück.
  • child::node() gibt die Kindknoten des Kontextknotens zurück.
  • attribute::EINHEIT ist die ausgeschriebene Schreibweise für das gebräuchliche @EINHEIT und gibt den Inhalt des Attributs EINHEITdes Kontextknotens zurück.
  • descendant::EUROPA gibt die Abkömmlinge vom Element <EUROPA> zurück.
  • self::EUROPA gibt sich zurück, falls der Kontextknoten gerade das Element <EUROPA> ist.
  • / gibt das Wurzelelement zurück.
  • //*/@* gibt beliebige Attribute eines beliebigen Elements zurück.
  • /child::comment() gibt alle Kommentarknoten zurück, die Kinder des Wurzelknotenssind.

Adressierung verschiedener Knotentypen

Bisher haben wir uns sehr start auf die Adressierung von Elementknoten konzentriert. Neben Elementen können aber auch alle anderen Kontentypen selektiert und zur Auswertung und weiteren Verarbeitung und Ausgabe herangezogen werden. Die nachfolgende Tabelle mit Beispieln zeigt die Möglichkeiten diese Kontenselektion vorzunehmen.

name/text() Soll der Textknoten des Elementes name angesprochen werden, geschieht dies durch den Knotentest text()
adresse/comment() Soll der Kommentarknoten des Elementes adresse angesprochen werden, geschieht dies durch den Knotentest comment()
ort/processing-instruction() Soll der PI-Knoten des Elementes ort angesprochen werden, geschieht dies durch den Knotentest processing-instruction()
adresse/node() Sollen alle Knotentypen (außer Attribute) angesprochen werden, geschieht dies durch den Knotentest: node()
<< zurück vor >>