168
Rudolf Jansen XQuery

XQuery. Eine praxisorientierte Einführung GERMAN

Embed Size (px)

Citation preview

Page 1: XQuery. Eine praxisorientierte Einführung  GERMAN

Rudolf Jansen

XQuery

Page 2: XQuery. Eine praxisorientierte Einführung  GERMAN
Page 3: XQuery. Eine praxisorientierte Einführung  GERMAN

Rudolf Jansen

XQuery Eine praxisorientierte Einführung

Software & Support Verlag 2004

Page 4: XQuery. Eine praxisorientierte Einführung  GERMAN

Jansen, Rudolf: XQuery. Eine praxisorientierte Einführung.

Frankfurt, 2004

ISBN 3-935042-65-5

© 2004 Software & Support Verlag GmbH

http://www.software-support-verlag.de

http://www.entwickler.com/buecher/xquery

Bibliografische Information Der Deutschen Bibliothek

Die Deutsche Bibliothek verzeichnet diese Publikation in der Deutschen

Nationalbibliografie; detaillierte bibliografische Daten sind im Internet über http://dnb.ddb.de abrufbar.

Umschlaggestaltung: Melanie Hahn

Korrektorat: Martha-Luise Lessing

Belichtung, Druck und Bindung: M.P. Media-Print Informationstechno-logie GmbH, Paderborn.

Alle Rechte, auch für Übersetzungen, sind vorbehalten. Reproduktion jeglicher Art (Fotokopie, Nachdruck, Mikrofilm, Erfassung auf elektro-nischen Datenträgern oder andere Verfahren) nur mit schriftlicher Ge-nehmigung des Verlags. Jegliche Haftung für die Richtigkeit des gesam-ten Werks kann, trotz sorgfältiger Prüfung durch Autor und Verlag, nicht übernommen werden. Die im Buch genannten Produkte,

Warenzeichen und Firmennamen sind in der Regel durch deren Inhaber geschützt.

Page 5: XQuery. Eine praxisorientierte Einführung  GERMAN

Inhaltsverzeichnis

5

Inhaltsverzeichnis

Vorwort.....................................................................................................7

1 Einführung..........................................................................................9

1.1 Zielgruppe ....................................................................................9 1.1.1 Themenabgrenzung............................................................9 1.1.2 Voraussetzungen..............................................................10 1.1.3 Kapitelübersicht ...............................................................11

1.2 Was ist XQuery? ........................................................................13 1.3 Standardisierung.........................................................................15

1.3.1 Historie.............................................................................15 1.3.2 Anforderungen .................................................................19 1.3.3 Andere XML-Standards...................................................20

1.4 Zusammenfassung......................................................................39

2 Sprachbestandteile ...........................................................................41

2.1 Beispieldaten ..............................................................................41 2.2 FLWOR-Ausdrücke ...................................................................44

2.2.1 Variablenbindung ............................................................50 2.2.2 Filterung...........................................................................53 2.2.3 Sortierung.........................................................................57 2.2.4 Rückgabewert ..................................................................61

2.3 Operatoren..................................................................................68 2.3.1 Logische Operatoren........................................................69 2.3.2 Arithmetische Operatoren................................................71 2.3.3 Vergleichs-Operatoren.....................................................72 2.3.4 Reihenfolge-Operatoren ..................................................83

2.4 Typkonzept.................................................................................85 2.4.1 Atomare Werte.................................................................87 2.4.2 Benutzerdefinierte Typen ................................................96 2.4.3 Typoperatoren..................................................................98 2.4.4 Konvertierung ................................................................102

Page 6: XQuery. Eine praxisorientierte Einführung  GERMAN

Inhaltsverzeichnis

6

2.5 Funktionen ...............................................................................103 2.5.1 Inputfunktionen .............................................................103 2.5.2 Vordefinierte Funktionen ..............................................105 2.5.3 Textfunktionen...............................................................109 2.5.4 Benutzerdefinierte Funktionen ......................................113 2.5.5 Externe Funktionen........................................................119

2.6 Module und Prolog...................................................................119 2.7 Joins..........................................................................................122 2.8 Fehlerbehandlung.....................................................................125

3 Implementierungen........................................................................129

3.1 Ausführungsschritte .................................................................131 3.1.1 Statische Verarbeitungsschritte .....................................132 3.1.2 Dynamische Verarbeitungsschritte................................134

3.2 Verfügbare Implementierungen ...............................................135 3.2.1 IPSI ................................................................................136 3.2.2 Qexo...............................................................................137 3.2.3 Sonstige .........................................................................141 3.2.4 BumbleBee ....................................................................144

3.3 Java-Anbindung .......................................................................145 3.3.1 Herstellerspezifische Lösungen.....................................146 3.3.2 XQJ................................................................................147

4 Anwendungen.................................................................................153

4.1 Systemintegration.....................................................................154 4.2 Webanwendungen....................................................................154 4.3 Fazit..........................................................................................155

Literatur ...............................................................................................159

Autor .....................................................................................................161

Index......................................................................................................163

Page 7: XQuery. Eine praxisorientierte Einführung  GERMAN

Vorwort

7

Vorwort

Die Zahl der im XML-Umfeld veröffentlichten Publikationen für neue Sprachbestandteile ist nur noch schwer zu überschauen. Aus diesem Grund habe ich der ersten Ankündigung eines weiteren neuen Standards mit Namen XQuery beim ersten Lesen keine besonders hohe Aufmerksamkeit geschenkt. Erst als ich einen kurzen Artikel über diesen weiteren Standard in einer Fach-zeitschrift gelesen hatte, bin ich neugierig geworden und habe mich intensi-ver mit XQuery beschäftigt. Da ich mich in meiner Tätigkeit als freiberuflicher Software-Entwickler häu-fig sowohl mit XML als auch mit relationalen Datenbanken und deren Ab-fragesprache SQL beschäftige, bin ich seit dem ersten intensiven Studium der neuen Sprache XQuery davon überzeugt, dass diese eine ähnliche Bedeutung wie SQL erlangen wird. Sehr schnell kam daher die Idee, ein einführendes Buch über XQuery zu schreiben, das im Vergleich zur sehr theorielastigen Sprachspezifikation praxisorientiert anhand von Sourcecode-Beispielen die wichtigsten Sprachbestandteile vorstellen soll.

Das größte „Hindernis“ bei der Entscheidung für dieses Buchprojekt war die Tatsache, dass die endgültige erste Version der Sprache XQuery zum Zeit-punkt der Erstellung dieses Buches im Sommer 2004 noch nicht verabschie-det war. Die im Frühjahr 2004 vorliegende relativ stabile Spezifikationsver-sion ist dann aber doch zur Grundlage für dieses Buch geworden. Auch wenn kleinere Änderungen am Sprachumfang in der endgültigen Version natürlich nie ganz auszuschließen sind, so sollten eigentlich keine gravierenden Ände-rungen an den grundlegenden Sprachbestandteilen, die in diesem Buch vor-gestellt werden, mehr zu erwarten sein. Für Fragen, Kritik und Anregungen stehe ich unter der Mailadresse [email protected] gerne zur Verfü-gung.

Page 8: XQuery. Eine praxisorientierte Einführung  GERMAN

Vorwort

8

Bedanken möchte ich mich bei den Mitarbeitern des Software & Support-Verlages für die Unterstützung bei der Planung und Erstellung dieses Buches sowie bei den Entwicklern der XQuery-Implementierung IPSI, die in Kapitel 3.2.1 dieses Buches vorgestellt wird und unter deren Einsatz ich die Beispiele dieses Buches entwickelt habe.

Der größte Dank gilt aber meiner Familie, ohne deren Geduld und Verständ-nis dieses Buchprojekt nicht möglich gewesen wäre.

Rudolf Jansen

Aachen, im August 2004

Page 9: XQuery. Eine praxisorientierte Einführung  GERMAN

Einführung

9

1 Einführung

1.1 Zielgruppe Wenn Sie sich für den Kauf dieses Buches entschieden haben oder gerade in der Buchhandlung zum ersten Mail in diesem Buch blättern, dann haben Sie wahrscheinlich den Begriff „XQuery“ schon vorher irgendwo gehört oder gelesen. Sie wissen also bereits, dass XQuery eine Abfragesprache für XML-Daten aller Art ist. Möglicherweise haben Sie auch bereits kleinere Beispiele dieser „neuen“ Sprache gesehen, die Sie neugierig gemacht haben.

Das vorliegende Buch ist eine praxisorientierte Einführung in die Abfrage-sprache XQuery, in dem anhand von Beispielen die zugrunde liegenden Kon-zepte und Sprachbestandteile vorgestellt werden. Neben der Sprache selber soll aber auch die Anwendung von XQuery behandelt werden. Zu diesem Zweck werden einige zum Zeitpunkt der Erstellung dieses Buches bereits verfügbare Implementierungen vorgestellt. Und auch die Frage, in welchen Anwendungen bzw. Projekten XQuery sinnvoll eingesetzt werden kann, sowie die Abgrenzung gegenüber verwandten Standards wie XML-Schema, XPath und XSLT sind Schwerpunkte dieses Buches.

1.1.1 Themenabgrenzung Bevor die Buchinhalte kurz vorgestellt werden, sollte zunächst festgelegt werden, was dieses Buch nicht ist bzw. welche Themen Sie besser in anderen Werken mit anderen Schwerpunkten suchen sollten.

Ziel des Buches ist – wie bereits erwähnt – eine praxisbezogene Einführung in XQuery. Daher wurde nicht mehr als unbedingt nötig von den theoreti-schen Grundlagen von XQuery sowie dem eng verwandten XPath in das Buch aufgenommen. Dies soll keine Abwertung der Theoriethemen darstel-len: Sie gehören zu jedem Standard dazu und bilden die Grundlage für die nach außen sichtbaren Praxis-Features. Eine umfassende Behandlung dieser Themen hätte aber einerseits den angestrebten Umfang dieses Buches ge-sprengt (alleine die W3C-Spezifikation zum „XPath 2.0 und XQuery 1.0“-

Page 10: XQuery. Eine praxisorientierte Einführung  GERMAN

Zielgruppe

10

Datenmodell umfasst knapp 60 Seiten). Außerdem wäre dann auch der Pra-xis-Schwerpunkt des Buches in den Hintergrund gerückt. Wer sich für De-tails der theoretischen Grundlagen interessiert, der sei entweder auf die zugrunde liegenden W3C-Spezifikationen [XQDM] oder das Buch [Kat03] verwiesen, in dem die Mitglieder der W3C-Arbeitsgruppe XQuery u.a. zu diesen Themen ausführliche Kapitel geschrieben haben.

Dieses Buch wendet sich an Nutzer der XQuery-Technologie, also an Perso-nen, die mithilfe einer vorliegenden XQuery-Implementierung die Sprache XQuery erlernen wollen und/oder XQuery in einem konkreten Projekt einset-zen wollen. In Kapitel 3 werden daher einige bereits verfügbare Implementie-rungen vorgestellt. Nicht Bestandteil dieses Buches sind dagegen Gesichts-punkte, die bei der Erstellung einer XQuery-Engine erforderlich sind. Bezüg-lich der dazu benötigten Kenntnisse beispielsweise auf dem Gebiet der Que-ry-Optimierung sei an dieser Stelle ebenfalls auf das Werk [Kat03] sowie diverse Publikationen zur Grundlagen-Forschung (z.B. [VLDB03], [XIME-04], [XSym03]) verwiesen.

1.1.2 Voraussetzungen Sie sollten über grundlegende XML-Kenntnisse verfügen, wenn Sie mit dem vorliegenden Buch XQuery erlernen wollen. Diese XML-Kentnisse müssen zwar nicht für alle XML-Details vorhanden sein, die wichtigsten XML-Begriffe wie Elemente, Attribute etc. sollten Ihnen aber bekannt sein.

Wie in den folgenden Abschnitten noch erläutert wird, ist XQuery mit den folgenden drei XML-Standards eng verknüpft:

• XML-Schema • XPath • XSLT

XSLT-Vorkenntnisse sind als Grundlage für dieses Buch nicht erforderlich. XQuery wird zwar häufig als Alternative bzw. Ergänzung zu XSLT angese-hen, sodass ein Leser mit XSLT-Kenntnissen beim Studium der XQuery-Beispiele unmittelbar die Gemeinsamkeiten und Unterschiede der beiden Sprachen erkennen kann. Aber auch für Leser, die XSLT erst gar nicht lernen

Page 11: XQuery. Eine praxisorientierte Einführung  GERMAN

Einführung

11

wollen bzw. müssen, sondern direkt XQuery einsetzen wollen, ist dieses Buch geeignet.

Die beiden erstgenannten XML-Standards (XML-Schema und XPath) dage-gen werden in XQuery-Konstrukten intensiv genutzt. XML-Schema dient als Grundlage für das Typkonzept von XQuery. XPath 2.0 wurde parallel zu XQuery 1.0 entwickelt, sodass Anforderungen von XQuery in diese neue XPath-Version eingeflossen sind. Diese beiden Standards werden daher be-reits am Ende dieses einführenden Kapitels vorgestellt und auch in den Bei-spielen in Kapitel 2 verwendet.

Da der Umfang dieses Buches bewusst knapp gehalten wurde, kann dieses Buch naturgemäß keine umfassende Referenz für XML-Schema und XPath sein. Zum Verständnis der XML-Schema- und XPath-Bestandteile der XQuery-Beispiele sollten die Ausführungen dieses Buches ausreichend sein. Wenn Sie nach Studium dieses Buches von den Möglichkeiten von XQuery überzeugt sind und daher detaillierter in die Nutzung dieser neuen Abfrage-sprache einsteigen wollen, lohnt sich sicherlich auch ein Blick auf Spezial-literatur zu den verwandten Standards, z.B. [VDF02] für XML-Schema und [Sim02] für XPath.

An vielen Stellen wird XQuery mit SQL verglichen werden. Nicht umsonst wird XQuery bereits in diesem sehr frühen Stadium als das „SQL des 21. Jahrhunderts“ bezeichnet. XQuery wird für den Bereich XML-Daten eine ähnliche Bedeutung vorausgesagt, wie es SQL für den Bereich „Relationale Datenbanken“ hat. SQL-Kenntnisse sind zwar nicht zwingend erforderlich, allerdings insbesondere bei den einführenden Beispielen zu den FLWOR-Ausdrücken in Kapitel 2 hilfreich, da die meisten Bestandteile von XQuery-Ausdrücken mit ähnlichen Bestandteilen von SQL-Abfragen vergleichbar sind.

1.1.3 Kapitelübersicht Was bietet Ihnen dieses Buch nun? Es ist genau das Richtige für Sie, wenn Sie zur beschriebenen Zielgruppe gehören, d.h. wenn Sie ein Buch mit fol-gender Zielsetzung gesucht haben:

Page 12: XQuery. Eine praxisorientierte Einführung  GERMAN

Zielgruppe

12

• Praxisbezogene Einführung in die neue Abfragesprache XQuery, • eher knappe Behandlung der theoretischen Grundlagen, • Beschränkung auf XQuery sowie die eng verknüpften Standards XML-

Schema und XPath, d.h. Verzicht auf Kapitel wie z.B. „Einführung in XML“,

• Vorstellung verfügbarer Tools mit der Möglichkeit, die Beispiele dieses Buches auf dem eigenen Rechner anhand (frei verfügbarer) XQuery-Engines testen und den eigenen Anforderungen z.B. in einem konkreten Projekt anpassen zu können,

• kritische Diskussion der Vor- und Nachteile, die XQuery in der ersten Version auszeichnen.

In den restlichen Abschnitten dieses ersten Kapitels folgt nun zunächst eine Kurzvorstellung von XQuery sowie der bei der Definition des Standards zugrunde liegenden Anforderungen. Kapitel 1 schließt mit der Vorstellung der mit XQuery eng verknüpften Standards XPath, XML-Schema und XSLT.

Hauptkapitel des Buches ist Kapitel 2. Dort werden anhand von Beispielen die wichtigsten Sprachbestandteile von XQuery vorgestellt (u.a. FLWOR-Ausdrücke, Operatoren, Typkonzept, Funktionen). Die Beispiele (XML-Dokumente und XQuery-Anfragen) stehen auf den Webseiten dieses Buches http://www.entwickler.com/buecher/xquery zum Download bereit, sodass Sie die Beispiele auch selber am Rechner ausprobieren bzw. sie als Grundlage für Ihre eigenen Skripte verwenden können.

Zum Testen der XQuery-Anfragen aus Kapitel 2 kann eine der bereits ver-fügbaren XQuery-Implementierungen eingesetzt werden. Kapitel 3 stellt eine Auswahl dieser in der Regel frei verfügbaren Engines vor. Die meisten Im-plementierungen bieten dabei nicht nur Kommandozeilen-Tools an, mit de-nen XQuery-Skripte aufgerufen werden können. Auch eine Java-Anbindung ist meist im Funktionsumfang enthalten. Ein Problem bei diesen Java-XQuery-APIs ist derzeit noch die herstellerspezifische Syntax. Obwohl die zugrunde liegende Technik bei allen Implementierungen sehr ähnlich bzw. identisch ist, unterscheiden sich die Implementierungen meist in den Details. Kapitel 3.3.2 stellt daher mit XQJ einen Versuch vor, an dieser Stelle einen herstellerübergreifenden Standard zu entwickeln. XQJ steht zwar zum Zeit-punkt der Erstellung dieses Buches erst in einer „Early Draft Review“-

Page 13: XQuery. Eine praxisorientierte Einführung  GERMAN

Einführung

13

Version zur Verfügung, aufgrund der darin schon zu erkennenden Ähnlich-keit zu JDBC ist aber bereits die Relevanz für die Etablierung von XQuery zu erkennen.

Spätestens nach der Einführung in die XQuery-Sprachbestandteile sowie den ersten eigenen Experimenten mit der neuen Abfragesprache werden Sie sich die Frage stellen, wo man dies alles in der Praxis sinnvoll einsetzen kann. Kapitel 4 liefert dazu einige Aspekte. Ein Schwerpunkt liegt dabei in der Kombination von Abfragen auf XML-Dokumenten und XML-Datenbanken, wobei XML-Datenbanken reine XML-Datenbanken, aber auch relationale Datenbanken mit XML-Erweiterungen sein können.

Als Abschluss des Buches folgt noch eine kurze Diskussion der Möglichkei-ten von XQuery. Neben der Frage, was XQuery in der derzeitigen ersten Version schon kann und wofür man es jetzt schon einsetzen kann, liegt ein Schwerpunkt dieses Kapitels auch auf den Features, die in der ersten Version noch fehlen. An dieser Stelle schon zu nennen sind dabei z.B. die fehlenden Update-Möglichkeiten.

Nach der Lektüre dieses Buches sollten Sie also in der Lage sein, die Mög-lichkeiten von XQuery zu beurteilen. Dazu zählt auf der positiven Seite das mit der wachsenden Verbreitung von XML-Daten in Form von Dokumenten und Datenbanken enorme Potenzial von XQuery, das dem etwas marketing-lastigen Slogan „XQuery – Das SQL des 21. Jahrhunderts“ in Zukunft durch-aus gerecht werden kann. Neben diesen Vorschusslorbeeren sind aber insbe-sondere in Verbindung mit der 1.0-Version von XQuery einige Kritikpunkte zu beachten, die Sie bei der Entscheidung, ob bzw. in welchen Konstellatio-nen Sie XQuery derzeit schon in produktiven Systemen einsetzen können, bedenken sollten.

1.2 Was ist XQuery? Kurz zusammengefasst ist XQuery eine typbasierte funktionale Abfragespra-che für XML-Daten. In dieser kurzen Definition enthalten sind mehrere Cha-rakteristika, die im Folgenden kurz erläutert werden sollen.

Page 14: XQuery. Eine praxisorientierte Einführung  GERMAN

Was ist XQuery?

14

Wie im folgenden Kapitel 1.3 besprochen wird, ist XQuery als Abfragespra-che für alle Arten von XML-Daten konzipiert worden, also insbesondere für die beiden großen Gruppen

• XML-Dokumente • XML-Datenbanken

Wie bereits erwähnt, liegt XQuery eine mit anderen Abfragesprachen ge-meinsame Vorgehensweise zugrunde. Vor allem Ähnlichkeiten zu SQL sind nicht zu übersehen.

Grundlegendes Konstrukt von XQuery sind Ausdrücke. Als deklarative Spra-che legt XQuery in Form von Ausdrücken fest, welche Daten aus den Input-Datenbeständen ausgewählt werden sollen. Der entscheidende Unterschied zu prozeduralen Sprachen wie z.B. Java besteht also darin, dass nicht der Weg definiert wird, wie ein Ergebnis erreicht werden soll, sondern nur das Ergeb-nis selber.

Für die Auswertung eines XQuery-Ausdrucks, also den Weg zur Konstrukti-on des Ergebnisses, ist nicht der XQuery-Nutzer, sondern die eingesetzte XQuery-Engine verantwortlich. Im Gegensatz zu prozeduralen Sprachen, bei denen in der Regel der Entwickler für die Festlegung des exakten Algorith-mus der Anwendung verantwortlich ist, kann bzw. muss man sich als Ent-wickler eines XQuery-Ausdrucks auf die in der eingesetzten XQuery-Engine vordefinierten Regeln zur Abarbeitung des Ausdruckes verlassen. Der Aus-wahl der passenden XQuery-Engine (s. Kapitel 3) kommt also eine hohe Bedeutung zu.

Durch die Festlegung vordefinierter Datentypen sowie die Möglichkeit, über XML-Schema-Definitionen weitere benutzerdefinierte Datentypen in XQue-ry-Ausdrücken zu verwenden, ist XQuery eine streng typbasierte Sprache. XQuery unterscheidet zwei Arten von Typüberprüfungen:

• dynamische Typüberprüfungen und • statische Typüberprüfungen. Während im Rahmen der dynamischen Typüberprüfung zur Laufzeit über-prüft wird, ob die im XQuery-Ausdruck definierten bzw. die aus Teilausdrü-cken ermittelbaren Typen mit denen in den Eingangsdaten übereinstimmen, bieten statische Typüberprüfungen ein interessantes Zusatzfeature gegenüber

Page 15: XQuery. Eine praxisorientierte Einführung  GERMAN

Einführung

15

einigen anderen Abfragesprachen. Statische Typüberprüfungen sind eher aus der Welt der prozeduralen Sprachen bekannt, in denen in der Compilephase u.a. Typfehler erkannt werden, sodass diese nicht erst zur Laufzeit bei der Verarbeitung der realen Daten auftreten. Im Rahmen der Vorstellung der XQuery-Sprachbestandteile in Kapitel 2 werden auch Beispiele zu fehlerhaf-ten XQuery-Ausdrücken gezeigt, die während der optionalen Phase der stati-schen Typüberprüfung entdeckt werden können.

1.3 Standardisierung

1.3.1 Historie Aufgrund der enorm wachsenden Bedeutung von XML nach dessen Einfüh-rung in der zweiten Hälfte der 90er-Jahre wurde auch sehr schnell die Nach-frage nach geeigneten Sprachen deutlich, mit denen man XML verarbeiten konnte. Auch wenn in den Anfangsstadien von XML sicher noch nicht ab-sehbar war, dass XML nicht nur als Datenaustauschformat sowie als Format von Konfigurationsdateien Erfolg haben würde, sondern zunehmend auch eine XML-basierte Speicherung von Daten in den Vordergrund treten würde, so war doch SQL als Gegenstück der „relationalen Konkurrenz“ als Vorbild zu erkennen.

XQuery-Vorgänger

Neben den heute weitläufig eingesetzten Standards wie XML-Schema, XPath und XSLT gab es auch eine Reihe von Versuchen, eine Abfragesprache für XML zu definieren, also ein „SQL für XML-Daten“. Die genannten Stan-dards wie XPath und XSLT können zwar auch für „abfrageähnliche“ Funkti-onen eingesetzt werden, ihr Schwerpunkt liegt aber eher auf der Navigation und Selektion innerhalb von XML-Dokumenten (XPath) sowie der Format-umwandlung von XML in andere XML-Darstellungen bzw. andere Formate wie z.B. HTML (XSLT). Eine vollständige Abfragesprache vergleichbar mit SQL sind diese Standards aber nicht.

Im Laufe der Zeit gab es mehrere Vorschläge für eine XML-Abfragesprache mit den folgenden Bezeichnungen:

Page 16: XQuery. Eine praxisorientierte Einführung  GERMAN

Standardisierung

16

• XML-QL • XQL • XSL • Lorel • XML-GL • Quilt

Die Ursprünge des XQuery-Standards reichen bis in das Jahr 1998 zurück, in dem das World Wide Web Consortium (W3C) einen Workshop zum Thema „XML-Abfragesprachen“ organisierte. Als Folge der auf dieser Konferenz vorgestellten Themen wurde eine Arbeitsgruppe eingesetzt, die sich im Jahre 1999 erstmals traf und am Entwurf einer XML-Abfragesprache arbeitete.

Abgrenzung gegenüber SQL

Eine der ersten Aufgaben dieser W3C-Arbeitsgruppe war eine Untersuchung, ob SQL geeignet erweitert werden kann, um auch in der XML-Welt einge-setzt zu werden. Kernfrage war dabei, wie XML-Daten – entweder in Doku-ment-Format oder XML-basiert in einer Datenbank gespeichert – abgefragt werden können. Dies ist nicht zu verwechseln mit der Aufgabe, eine XML-Darstellung von relational gespeicherten Daten zu generieren. Dazu gibt es inzwischen neben herstellerspezifischen SQL-Erweiterungen auch den SQL/XML-Standard, der einige Funktionen wie z.B. XMLElement(), XMLAgg() oder XMLForest() zur Verfügung stellt, mit denen innerhalb von normalen SQL-Select-Abfragen eine XML-Darstellung von relational ge-speicherten Daten erzeugt werden kann.

Ergebnis der Evaluation von SQL als Kandidat für eine XML-Abfrage-sprache war allerdings eine Reihe von grundlegenden Unterschieden zwi-schen relationalen Datenbanken als „Zielgruppe“ von SQL-Abfragen und XML-Daten, die zu der Entscheidung führte, eine neue Sprache zu definie-ren, die besser auf diese XML-Besonderheiten zugeschnitten ist:

• XML liegt eine hierarchische Datenstruktur zugrunde im Gegensatz zur flachen tabellenbasierten Speicherung von relationalen Daten.

• Derselbe Unterschied (hierarchische XML-Form gegenüber flachem Tabellenformat) besteht auch beim Ergebnisformat einer XML-Abfrage.

Page 17: XQuery. Eine praxisorientierte Einführung  GERMAN

Einführung

17

• Bei einer relationalen Speicherung spielt die Sortierung der Daten keine Rolle. Innerhalb von XML-Dokumenten besteht jedoch eine Ordnung innerhalb der Knotenmenge. Diese Ordnung muss daher auch bei Abfra-gen berücksichtigt werden können.

• Erfahrungsgemäß sind relationale Tabellen dichter gefüllt als XML-Dokumente. Gemeint ist damit die Tatsache, dass in relationalen Tabel-len alle vordefinierten Spalten auch mit Werten belegt sind (entweder mit „realen“ Daten oder mit NULL-Werten). XML-Dokumente dagegen sind häufig dadurch gekennzeichnet, dass sie lückenhafter sind, d.h. nicht alle Elemente gleichen Typs müssen zwangsläufig dieselbe Struk-tur haben. Ein Beispiel wäre eine Patientendatei in XML-Format: Inner-halb einer XML-Schema-Definition müssen zu allen möglichen Krank-heiten, die ein Patient haben kann, Formate (Elemente, Attribute, Constraints etc.) definiert sein, in denen diese dargestellt werden können. In der Realität wird aber natürlich nicht jeder Patient jede Krankheit ha-ben, sodass viele vordefinierte Bestandteile in den auf der XML-Schema-Definition beruhenden XML-Dokumenten fehlen werden. Eine XML-Abfragesprache muss auf solche fehlenden bzw. unterschiedlichen Bestandteile ausgerichtet sein.

Zeitplan

Nach der Entscheidung, eine neue XML-Abfragesprache zu definieren, legte die W3C-Arbeitsgruppe, die aus Vertretern von namhaften Firmen und Insti-tuten besteht, im Jahr 2001 einen ersten Entwurf für eine Sprache namens XMLQuery vor. Diese Bezeichnung wurde dann später in XQuery umge-wandelt.

Ein Hauptziel beim Entwurf von XQuery war eine Integration in die beste-hende Familie von XML-Standards. Über die grundlegende Definition des XML-Standards hinaus wurde insbesondere durch XML-Schema und XPath bereits viel Vorarbeit geleistet, die beim Entwurf von XQuery natürlich be-rücksichtigt werden sollte.

Vor allem XPath, das bereits im Jahre 1999 als W3C Recommendation vor-lag, wurde in Praxisanwendungen bereits intensiv zur Navigation innerhalb von XML-Daten eingesetzt. Da innerhalb einer XML-Abfragesprache die Themen Navigation und Selektion eine zentrale Rolle spielen und XPath

Page 18: XQuery. Eine praxisorientierte Einführung  GERMAN

Standardisierung

18

bereits in anderen XML-Standards wie z.B. XSLT für diese Zwecke einge-setzt wurde, lag es nahe, XPath-Funktionalität auch innerhalb von XQuery zu nutzen.

Der Einfluss zwischen den beiden Standards XPath und XQuery bestand aber nicht nur von XPath zu XQuery. Auch XPath selber wurde u.a. durch Anfor-derungen aus dem XQuery-Umfeld weiterentwickelt. Und auch die W3C-Arbeitsgruppe zu XSLT hatte eine Reihe von Erweiterungswünschen zum von XSLT genutzten XPath. Die XSLT- und XQuery-Anforderungen bilde-ten dann die Grundlage für die Version 2.0 von XPath, die somit zum zentra-len Bestandteil von XQuery 1.0 geworden ist. Der beste „Beweis“ für diese enge Verzahnung zwischen XQuery 1.0 und XPath 2.0 ist die Tatsache, dass beide W3C-Standards auf einem gemeinsamen Datenmodell beruhen [XQDM].

Nach Vorlage des ersten Entwurfs der XQuery-Spezifikation im Jahre 2001 begann eine ausführliche und damit auch zeitaufwändige Diskussion über die endgültige Form des Standards. Die Ankündigung „Verabschiedung des XQuery-Standards steht kurz bevor“ war auf Konferenzen und Web-Diskussionsgruppen zwar häufig zu hören, die endgültige Verabschiedung zog sich aber recht lange hin.

Zum Zeitpunkt der Erstellung dieses Buches in der Mitte des Jahres 2004 lag immer noch keine endgültige Verabschiedung des XQuery-Standards vor. Die im November 2003 veröffentlichte Version kann allerdings als sehr stabil angesehen werden und wird aller Voraussicht nach – abgesehen von kleine-ren Änderungen und Umformulierungen – als W3C Recommendation übernommen werden.

Auf der Basis der November 2003-Spezifikation existiert bereits eine Viel-zahl von Veröffentlichungen und Implementierungen. Auch die Beispiele des vorliegenden Buches beruhen auf dieser Version des XQuery-Standards. Abweichungen vom kurz vor der Verabschiedung stehenden offiziellen Stan-dard XQuery 1.0 sind zwar unwahrscheinlich, aber natürlich nicht völlig auszuschließen. Wenn Sie also die Beispiele dieses Buches mit einer XQue-ry-Implementierung nutzen, die nicht auf der November 2003-Spezifikation, sondern auf einer späteren Version des Standards beruht, und bei diesem Einsatz Inkonsistenzen gegenüber den Angaben in diesem Buch auftreten sollten, so könnte die Ursache in unmittelbar vor der Verabschiedung aufge-

Page 19: XQuery. Eine praxisorientierte Einführung  GERMAN

Einführung

19

nommenen Änderungen liegen. Nicht nur in diesem Fall lohnt sich ein Blick auf die Webseite dieses Buches, wo Sie in diesen Fällen Updates zu den Beispielen finden werden (http://www.entwickler.com/buecher/xquery).

Mit der Verabschiedung der XQuery 1.0-Version ist die Entwicklung von XQuery aber sicherlich noch nicht abgeschlossen. Im Vorgriff auf das ab-schließende Kapitel dieses Buches, in dem die Vor- und Nachteile der ersten XQuery-Version diskutiert werden, sei an dieser Stelle bereits auf zwei Fea-tures verwiesen, die zum Teil aus Komplexitätsgründen und daher mit der Zielsetzung, die Verabschiedung der ersten Version nicht noch weiter nach hinten zu verschieben, von der W3C-Arbeitsgruppe nicht in Version 1.0 aufgenommen wurden. Es handelt sich dabei um Volltext-Suchfunktionen und Update-Möglichkeiten.

Insbesondere der Verzicht auf Update-Möglichkeiten hat einerseits in ersten Beurteilungen von XQuery zu Kritik geführt. Andererseits wurden einige der zum derzeitigen frühen Zeitpunkt bereits verfügbaren Implementierungen (s. Kapitel 3) um herstellerspezifische Erweiterungen beim Thema Updatemög-lichkeiten ergänzt. Anlass für solche Erweiterungen war sicherlich auch der Blick auf die „Konkurrenz“ SQL. Ein SQL ohne Update-, Insert- und Delete-Funktionen, also ein reines Read-Only-SQL ist eigentlich kaum vorstellbar bzw. nur in einer weitaus geringeren Zahl von Projekten einsetzbar. Analog wird auch XQuery in zukünftigen Versionen nicht nur an dieser Stelle erwei-tert werden. Veröffentlichungen der Mitglieder der W3C-Arbeitsgruppe zei-gen, dass dieses „Problem“ erkannt wurde und daher mit einer Weiterent-wicklung des Standards zu rechnen ist.

1.3.2 Anforderungen Eines der ersten Dokumente, die die W3C-Arbeitsgruppe zum Thema XQuery veröffentlicht hat, war mit [XQR] eine Zusammenstellung der An-forderungen an die neu zu definierende Sprache. Neben einigen Anforderun-gen an die Sprache selber (wie z.B. eine für Menschen lesbare Syntax, Dekla-rativität und Protokollunabhängigkeit) sind dort u.a. auch folgende erwartete Einsatzgebiete für die Sprache aufgelistet:

• Verarbeitung aller Arten von XML-Dokumenten. Zu unterscheiden sind dabei datenorientierte und dokumentenorientierte XML-Dokumente.

Page 20: XQuery. Eine praxisorientierte Einführung  GERMAN

Standardisierung

20

Während datenorientierte XML-Dokumente meist aus relational gespei-cherten Daten erzeugt werden und daher eine klare Struktur aufweisen, kann man dokumentenorientierte Dokumente eher als „Freitext in XML-Format“ kennzeichnen. Aber auch Mischformen zwischen diesen beiden Typen sind möglich: Bei solchen hybriden XML-Dokumenten liegt meist ein „Header-Body-Aufbau“ vor, in dem nach einem klar struktu-rierten Teil im Header des Dokumentes ein weniger strukturierter Teil folgt. Beispiele für solche Mischformen sind Börsenberichte, bei denen zunächst nach einem festgelegten Muster die relevanten Informationen zur untersuchten Aktie (Name, WKN, aktueller Kurs etc.) angegeben sind, bevor dann in „Freiformat“ die eigentliche Nachricht aufgelistet wird.

• Verarbeitung von Konfigurationsdateien, bei denen sich XML als Daten-format durchgesetzt hat.

• Filterung von Datenströmen analog zur UNIX-Filterverarbeitung z.B. bei größeren Logging-Datenströmen.

• Abfragen auf DOM (Document Object Model)-Strukturen Neben diesen Anforderungen an die zu verarbeitenden Inputdaten sollte XQuery auch möglichst unabhängig von der Systemumgebung sein. Eine XQuery-Abfrage innerhalb einer URL oder einer JSP-Seite sollte genauso möglich sein wie die Einbindung in Programmiersprachen.

1.3.3 Andere XML-Standards Bereits im einführenden Kapitel 1.1 wurde die enge Verknüpfung von XQuery mit weiteren (XML-)Standards erwähnt. Dies ist natürlich kein Zu-fall, sondern bewusst aufgrund der breiten Standard-Abdeckung des gesam-ten XML-Bereiches erfolgt. Die enge Verzahnung wurde u.a. dadurch er-reicht, dass die W3C-Arbeitsgruppen, die sich mit der Erstellung der Weiter-entwicklung ähnlicher Standards befassen, gemeinsame Sitzungen mit der XQuery-W3C-Arbeitsgruppe durchgeführt haben. Auf diese Weise konnten die gegenseitigen Anforderungen bei der (Weiter-)Entwicklung der XML-Standards berücksichtigt werden.

Page 21: XQuery. Eine praxisorientierte Einführung  GERMAN

Einführung

21

Neben den grundlegenden XML-Standards, in denen die XML-Syntax und die Semantik festgelegt wurden, sind für XQuery vor allem die folgenden drei Standards relevant:

• XPath • XML-Schema • XSLT

Dabei ist vor allem XPath in Version 2.0 so eng mit XQuery verwandt, dass ein XQuery-Neueinsteiger, der sich bereits mit XPath 2.0 beschäftigt hat, in kürzester Zeit die zusätzlichen XQuery-Features lernen kann. Schätzungen zufolge besteht XQuery 1.0 zu 80% aus XPath 2.0, da die Selektion, Naviga-tion und Auswahl von XML-Fragmenten aus Inputdaten über XPath-Features erfolgt und somit die zentrale Komponente von XQuery darstellt.

Abbildung 1.1 zeigt die Verzahnung der drei XML-Standards. XPath 2.0 bildet die Grundlage sowohl für XSLT als auch für XQuery. Wie in Kapitel 2.4 noch genauer erläutert wird, bietet eine XML-Schema-Definition die Möglichkeit, benutzerdefinierte Datentypen innerhalb von XQuery-Anfragen zu verwenden.

Abbildung 1.1: Abhängigkeiten der XML-Standards

Page 22: XQuery. Eine praxisorientierte Einführung  GERMAN

Standardisierung

22

XPath

XPath wurde im Jahr 1999 durch das W3C verabschiedet und ist eine Spra-che zur Lokalisierung von Teilen eines XML-Dokumentes. XPath wird in einer Vielzahl von XML-Standards und Tools eingesetzt und ist vergleichbar mit den Regulären Ausdrücken, mit denen in der Nicht-XML-Welt bestimm-te Konstrukte innerhalb von Textdateien gesucht werden können.

XPath arbeitet auf einer Baumansicht eines XML-Dokumentes. Dabei wer-den die folgenden sieben Knotentypen unterschieden:

• Wurzelknoten: ein virtueller Knoten, der nicht aus dem zugrunde liegen-den Dokument entnommen ist und als Einstiegspunkt in das Dokument dient

• Elementknoten • Attributknoten • Textknoten für Text innerhalb von Elementen • Namensraumknoten, falls entsprechende Namensraumangaben im Do-

kument vorliegen • Verarbeitungsanweisungsknoten • Kommentarknoten

Ein XPath-Ausdruck besteht aus einer Folge von Lokalisierungsschritten. Jeder Lokalisierungsschritt selektiert dabei eine Teilmenge der Knoten eines Dokumentes. Diese Ergebnismenge eines Lokalisierungsschrittes ist dann der Ausgangspunkt für den nächsten Lokalisierungsschritt. Entsprechend den Angaben des nächsten Lokalisierungsschrittes wird – ausgehend von der Knotenmenge, die beim vorhergehenden Lokalisierungsschritt ermittelt wur-de – eine neue Knotenmenge selektiert. In Abhängigkeit der beim Lokalisie-rungsschritt verwendeten Achsenangaben kann die selektierte Knotenmenge dabei auch größer werden.

Syntaktisch sieht ein Lokalisierungsschritt wie folgt aus:

Achse::Knotentest[Prädikate]

Er besteht aus den folgenden drei Bestandteilen:

• Achse: gibt die Richtung an, in der die neu zu selektierenden Knoten ausgehend von der Ausgangs-Knotenmenge gesucht werden sollen.

Page 23: XQuery. Eine praxisorientierte Einführung  GERMAN

Einführung

23

• Knotentest: Einschränkung der durch die Achsenangabe erreichbaren Knoten durch Angabe von geforderten Knotennamen oder Knotentypen (z.B. comment() als Angabe für Kommentarknoten).

• Prädikate: Über Prädikate können optional weitere Filterbedingungen angegeben werden. Dazu werden XPath-Ausdrücke benutzt, aus denen für jeden über Achse und Knotentest selektierten Knoten ein boolean-Wert ermittelt wird, der über die Aufnahme des betreffenden Knotens in die Ergebnismenge des Lokalisierungsschrittes entscheidet. Verwendet werden können in solchen Ausdrücken auch XPath-eigene Funktionen. Neben String-Funktionen (concat(), substring(),…) und Boolean-Funktionen ( contains(), not(), …) stellt XPath auch Funktionen be-reit, die sich mit der Ordnung innerhalb von XML-Dokumenten beschäf-tigen (position(), last(), …).

Über die Angabe einer Achse wird ausgehend von einem Kontextknoten (also dem Ergebnisknoten des vorherigen Lokalisierungsschrittes) eine be-stimmte Menge von Knoten für den nächsten Schritt adressiert. In einer Folge von Lokalisierungsschritten kann es sich auch um eine Menge von Kontext-knoten handeln. In diesem Fall wird der durch die Achse festgelegte Schritt für jeden Knoten dieser Knotenmenge durchgeführt und anschließend zu einer Knotenmenge zusammengefügt, für die dann die weiteren Bestandteile des Lokalisierungsschrittes (Knotentest und optionale Prädikate) angewendet werden.

Folgende Achsen können innerhalb von Lokalisierungsschritten angegeben werden:

• self: Selektiert den Kontextknoten selber • child: alle Kinder des Kontextknotens. Attribut- und Namensraumkno-

ten sind im Sinne dieser Achse keine Kinder eines Knotens. Für den Zugriff auf Attribut- oder Namensraumknoten existieren die folgenden beiden Achsenangaben.

• attribute: Selektiert alle Attributknoten des Kontextknotens • namespace: Selektiert alle Namensraumknoten des Kontextknotens • parent: der Elternknoten des Kontextknotens • descendant: selektiert alle Nachkommen in der Baumdarstellung, also

die Kinder, deren Kinder usw.

Page 24: XQuery. Eine praxisorientierte Einführung  GERMAN

Standardisierung

24

• descendant-or-self: selektiert alle Nachkommen inklusive des Kon-textknotens

• ancestor: selektiert alle Vorgänger in der Baumdarstellung, also den Elternknoten sowie rekursiv alle weiteren Elternknoten bis zum Wurzel-knoten

• ancestor-or-self: selektiert alle Vorgänger inklusive des Kontext-knotens

• following: alle Nachfolger in der Dokumentreihenfolge. Zu beachten ist also der Unterschied zwischen den über die Achse descendant se-lektierten Nachfolgern in der Baumdarstellung und den über following selektierten Nachfolgern in der Dokumentdarstellung, d.h. following selektiert alle Knoten, die im zugrunde liegenden XML-Dokument nach dem Kontextknoten aufgelistet sind.

• following-sibling: alle nachfolgenden Geschwisterknoten in der Dokumentreihenfolge. Geschwisterknoten sind Knoten, die denselben Elternknoten besitzen.

• preceding: alle Vorgänger in der Dokumentreihenfolge. Zu beachten ist auch hier der Unterschied zwischen den über die Achse ancestor se-lektierten Vorgängern in der Baumdarstellung und den über preceding selektierten Vorgängern in der Dokumentdarstellung.

• preceding-sibling: alle vorhergehenden Geschwisterknoten in der Dokumentreihenfolge.

Für einige dieser Achsen existieren Abkürzungen, die in der Regel innerhalb von XPath-Beispielen zu finden sind, z.B.

• child:: kann komplett entfallen • attribute:: kann durch ein @-Zeichen abgekürzt werden • descendant-or-self:: kann durch // abgekürzt werden

Das folgende Beispiel zeigt die Navigation und Selektion innerhalb von XML-Dokumenten über XPath-Ausdrücke. Abbildung 1.2 zeigt eine verein-fachte Baumdarstellung des folgenden XML-Dokumentes:

Page 25: XQuery. Eine praxisorientierte Einführung  GERMAN

Einführung

25

<?xml version="1.0" encoding="UTF-8"?>

<Personenliste>

<Person>

<Name>Schmitz</Name>

<Adresse Adr_Id="1">

<Adr_Strasse>Hauptstrasse</Adr_Strasse>

<Adr_Plz>12345</Adr_Plz>

<Adr_Ort>Entenhausen</Adr_Ort>

</Adresse>

</Person>

<Person>

<Name>Meier</Name>

<Adresse Adr_Id="1">

<Adr_Strasse>Schlossallee</Adr_Strasse>

<Adr_Plz>99999</Adr_Plz>

<Adr_Ort>XYZ-Stadt</Adr_Ort>

</Adresse>

<!-- Ferienwohnung -->

<Adresse Adr_Id="2">

<Adr_Strasse>Turmstrasse</Adr_Strasse>

<Adr_Plz>11111</Adr_Plz>

<Adr_Ort>ABC-Dorf</Adr_Ort>

</Adresse>

</Person>

<Person>

<Name>Mueller</Name>

<Adresse Adr_Id="1">

<Mail>[email protected]</Mail>

</Adresse>

</Person>

</Personenliste>

Page 26: XQuery. Eine praxisorientierte Einführung  GERMAN

Standardisierung

26

Abbildung 1.2: Baumdarstellung eines XML-Dokumentes

Anhand des folgenden XPath-Ausdrucks soll nun die Vorgehensweise bei der Auswertung von XPath-Ausdrücken illustriert werden:

/child::Personenliste/child::Person[Name="Mueller"]/

preceding::Adresse/child::Plz

bzw. in abgekürzter Schreibweise

/Personenliste/Person[Name="Mueller"]/preceding::Adresse/

Plz

Dieser XPath-Ausdruck besteht aus vier Lokalisierungsschritten. Die Ergeb-nismenge des ersten Schrittes

/child::Personenliste

besteht aus dem (einzigen) Personenliste-Knoten. Ausgehend von dieser einelementigen Knotenmenge werden über den zweiten Schritt

/child::Person[Name="Mueller"]

Page 27: XQuery. Eine praxisorientierte Einführung  GERMAN

Einführung

27

zunächst unter den Kindern (Achse = child) dieses Knotens alle Knoten mit Namen Person (Knotentest = Person) ausgewählt. Dies wären also eigent-lich alle drei Person-Elemente direkt unterhalb der Personenliste. Durch die zusätzliche Angabe eines Prädikates – in diesem Fall durch die Filterbe-dingung Name="Mueller" – wird diese zunächst dreielementige Knoten-menge auf eine einelementige Menge reduziert. Diese ist in Abbildung 1.3 schraffiert gekennzeichnet und stellt die Ergebnismenge des zweiten Lokalisierungsschrittes dar.

Abbildung 1.3: XPath-Navigation (1)

Der dritte Lokalisierungsschritt

/preceding::Adresse

geht nun von dieser in Abbildung 1.3 schraffiert gekennzeichneten einele-mentigen Knotenmenge aus und selektiert über die preceding-Achse zu-nächst alle in Dokumentreihenfolge vorhergehenden Knoten. Dies sind also alle in Abbildung 1.3 gestrichelt umrandeten Knoten. Über die Knotentest-Angabe Adresse werden daraus nun alle Adresse-Knoten ausgewählt. Da in diesem Lokalisierungsschritt kein optionales Prädikat zur weiteren Ein-

Page 28: XQuery. Eine praxisorientierte Einführung  GERMAN

Standardisierung

28

schränkung der Knotenmenge angegeben ist, besteht die Ergebnismenge dieses dritten Lokalisierungsschrittes also aus den drei in Abbildung 1.4 schraffiert gekennzeichneten Adresse-Knoten. Dieser dritte Lokalisierungs-schritt ist also ein Beispiel dafür, dass sich die selektierte Knotenmenge durch einen weiteren Schritt auch vergrößern lässt.

Abbildung 1.4: XPath-Navigation (2)

Abschließend werden ausgehend von dieser Knotenmenge über den letzten Lokalisierungsschritt

/child::Plz

unter allen Kinderknoten dieser drei Adresse-Knoten noch alle PLZ-Knoten selektiert. Ergebnis des gesamten XPath-Ausdruckes

/child::Personenliste/child::Person[Name="Mueller"]/

preceding::Adresse/child::Plz

bzw. in Kurzform

/Personenliste/Person[Name="Mueller"]/preceding::Adresse/

Plz

Page 29: XQuery. Eine praxisorientierte Einführung  GERMAN

Einführung

29

ist also die in Abbildung 1.5 schraffiert gekennzeichnete Knotenmenge mit drei PLZ-Knoten.

Abbildung 1.5: XPath-Navigation (3)

Weitere Beispiele für XPath-Ausdrücke folgen in Kapitel 2 bei der Vorstel-lung der XQuery-Sprachbestandteile.

XPath in der Version 1.0 kennt nur vier Datentypen:

• boolean • node-set (Knotenmenge) • number

• string

Eine der für XQuery wichtigen Erweiterungen in XPath 2.0, das die Grund-lage für XQuery 1.0 bildet, ist eine Erweiterung dieses Typkonzeptes u.a. durch die Möglichkeit, über XML-Schema definierte Datentypen zu verwen-den. XPath selber ist aber noch keine XML-Abfragesprache, da zwar die Selektion von XML-Fragmenten möglich ist, nicht aber die Kombination mehrerer Fragmente zu einer Ergebnismenge. An dieser Stelle setzt dann XQuery an und erweitert die durch XPath 2.0 verfügbaren Selektionsmög-lichkeiten entsprechend.

Page 30: XQuery. Eine praxisorientierte Einführung  GERMAN

Standardisierung

30

XSLT

Wie bereits mehrfach erwähnt, hat sich XML vor allem als Standard im Be-reich Datenaustauschformate etabliert. Zwischen verschiedenen Anwendun-gen, aber auch über Unternehmensgrenzen hinweg werden häufig XML-Formate in Form von XML-Schema-Definitionen entwickelt, die dann zur Integration der unterschiedlichsten Systeme eingesetzt werden.

Nicht immer ist ein auf diese Art definiertes XML-Format aber exakt das, was innerhalb der Anwendungen benötigt wird. Gesucht ist also häufig eine Möglichkeit, aus einem anwendungsspezifischen Format das erforderliche XML-Format zu generieren oder umgekehrt. Dabei muss es sich bei dem anwendungsspezifischen Format nicht zwingend auch um ein XML-Format handeln. Auch andere Textformate wie z.B. HTML, WML oder ein ASCII-Format sind denkbar.

Abbildung 1.6: XSLT

Für die Transformation von einem XML-Format in ein anderes XML-Format bzw. in ein anderes Textformat kann XSLT eingesetzt werden. Die Vorge-hensweise bei einer XSLT-Transformation zeigt Abbildung 1.6. Die für die Transformation benötigten Regeln – also Aussagen darüber, welche Inhalte aus dem Input-Dokument in welcher Formatierung im Output-Dokument

Page 31: XQuery. Eine praxisorientierte Einführung  GERMAN

Einführung

31

auftauchen sollen – enthält die XSLT-Stylesheet-Datei, die wiederum als XML-Dokument spezifiziert wird.

Das folgende Beispiel zeigt ein minimales Stylesheet:

<?xml version="1.0" encoding="UTF-8"?>

<xsl:transform version="1.0"

xmlns:xsl="http://www.w3.org/1999/XSL/Transform"/>

Dieses Stylesheet enthält unterhalb des Wurzelelementes transform aus dem Namensraum http://www.w3.org/1999/XSL/Transform keine Umwandlungsregeln, d.h. Input-Dokumente werden im Prinzip1 unverändert ausgegeben.

Transformationsregeln werden in Form von Schablonen angegeben. Jede Schablone ist gekennzeichnet durch ein template-Element, bei dem über das Attribut match ein XPath-Ausdruck angegeben werden muss, der dieje-nigen Bestandteile des Inputdokumentes selektiert, die transformiert werden sollen. Das folgende Beispiel enthält genau eine Transformationsregel.

<?xml version="1.0" encoding="UTF-8"?>

<xsl:transform version="1.0"

xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="//PLZ">

<Postleitzahl>

<xsl:copy-of select="child::*"/

</Postleitzahl>

</xsl:template>

</xsl:transform>

Durch den XPath-Ausdruck //PLZ2 im match-Attribut der Transformations-regel wird hier festgelegt, dass alle PLZ-Knoten innerhalb des Dokumentes

1 Das Outputdokument enthält ohne Angabe von Transformationsregeln alle Character Information Items. Dabei handelt es sich um die Ansammlung von allen Textinforma-tionen innerhalb des Dokumentes. 2 Wie bereits im vorhergehenden Abschnitt über XPath erwähnt, werden in der Regel Kurznotationen für einige ausgewählte XPath-Achsen verwendet. In diesem Beispiel

Page 32: XQuery. Eine praxisorientierte Einführung  GERMAN

Standardisierung

32

transformiert werden sollen. Jedes gemäß dem match-Attribut ermittelte Element – in diesem Beispiel also jedes PLZ-Element – wird nun durch den innerhalb der Schablone angegebenen Ausdruck ersetzt, hier also durch den Ausdruck

<Postleitzahl>

<xsl:copy-of select="child::*"/

</Postleitzahl>

Ergebnis wäre in diesem Beispiel also eine Umwandlung von PLZ-Elementen in Postleitzahl-Elemente mit identischem Inhalt, denn über den Ausdruck

<xsl:copy-of select="child::*"/

werden alle Kindknoten der innerhalb der Schablone zu bearbeitenden Kno-tenmenge unverändert übernommen.

Ein XSLT-Stylesheet setzt sich in der Regel aus mehreren solcher tem-plate-Schablonen zusammen. Aufgabe des XSLT-Prozessors ist dann die korrekte Anwendung dieser Schablonen. Gemäß einer vordefinierten Reihen-folge, die allerdings auch über spezielle Konstrukte innerhalb der Stylesheet-Datei geändert werden kann, sucht der XSLT-Prozessor durch Auswertung der in der Stylesheet-Datei enthaltenen XPath-Ausdrücke nach passenden Schablonen, die auf die Bestandteile der Inputdatei angewendet werden müs-sen.

Natürlich bietet XSLT wesentlich mehr Funktionalität, als in diesem kleinen Beispiel ersichtlich ist. Da das vorliegende Buch aber keine Einführung in XSLT sein soll, sei an dieser Stelle auf entsprechende XSLT-Fachliteratur verwiesen [FIT03]. Sinn dieser kurzen Einführung in XSLT war die Verdeut-lichung der engen Verzahnung von XPath und XSLT. Wie bereits aus obi-gem Beispiel ersichtlich ist, werden Kernaufgaben innerhalb von XSLT über XPath-Ausdrücke spezifiziert, insbesondere innerhalb der Schablonen zur Adressierung der umzuwandelnden Inputdaten.

handelt es sich um die Abkürzung //, die der descendant-Achse entspricht und daher alle Nachkommen in der Baumdarstellung adressiert.

Page 33: XQuery. Eine praxisorientierte Einführung  GERMAN

Einführung

33

Vergleich mit XQuery

Und was hat das Ganze nun mit XQuery zu tun? In der grundlegenden Auf-gabenstellung sind durchaus Gemeinsamkeiten zwischen XSLT und XQuery zu erkennen. Beide arbeiten auf einem XML-formatierten Input und liefern auch XML-formatierten Output. Beide beschäftigen sich mit der Selektion von XML-Konstrukten und beruhen daher beide auf XPath. Auch eine reine Formatumwandlung von einem XML-Format in ein anderes ist sowohl mit XSLT als auch mit XQuery möglich.

Insbesondere XSLT-Profis, die bereits Erfahrung mit den Möglichkeiten gesammelt haben, die sich bei einer geschickten Kombination von Schablo-nen und weiteren XSLT-Techniken bieten, werden sich also fragen, warum überhaupt eine neue XML-Abfragesprache entwickelt wird und warum man stattdessen nicht die bestehenden XPath- und XSLT-Features nutzt und er-weitert.

Beim Vergleich von XSLT und XQuery ist abseits des Funktionsumfanges die Komplexität der Sprache ein Unterscheidungsmerkmal – wobei natürlich direkt angemerkt werden muss, dass die Schwierigkeit beim Erlernen und Einsetzen einer neuen Sprache immer eine subjektive Einschätzung beinhal-tet. Wer bereits umfangreiche Erfahrung mit XSLT gesammelt hat, wird sich für viele der im Folgenden aufgeführten XQuery-Beispiele eine vergleichbare Vorgehensweise in XSLT vorstellen können. Aber allein die Tatsache, dass XSLT ein rekursives Vorgehen bei der Anwendung der einzelnen Schablo-nen-Regeln erfordert, macht die Sprache für einen „prozedural denkenden“ Entwickler komplexer, als es XQuery beim Erlernen ist. Und auch die Tatsa-che, dass XSLT-Stylesheets selber in XML geschrieben sind, während XQuery-Skripte eine Syntax besitzen, die nicht nur auf den ersten Blick Ähn-lichkeiten zu SQL aufweist, ist zwar für einen Profi keine entscheidendes Argument, kann aber für den Einstieg in eine neue Sprache durchaus eine zusätzliche Hürde darstellen.

Ein wichtiger Unterschied zwischen XSLT und XQuery ist das zugrunde liegende Typsystem. Durch die Möglichkeit, über eine XML-Schema-Definition benutzerdefinierte Datentypen innerhalb von XQuery-Ausdrücken zu verwenden, sowie durch die größere Anzahl von vordefinierten Datenty-pen (XQuery definiert insgesamt 59 solcher Datentypen) bietet XQuery auf diesem Gebiet wesentlich mehr Möglichkeiten als XSLT.

Page 34: XQuery. Eine praxisorientierte Einführung  GERMAN

Standardisierung

34

Beim Vergleich von XPath und XQuery muss natürlich zunächst festgestellt werden, dass XQuery eine Obermenge von XPath ist, d.h. grundsätzlich lässt sich alles, was mit XPath machbar ist, auch mit XQuery realisieren. Was aber sind die Zusatzfeatures, die XQuery bietet und mit denen es sich von XPath unterscheidet? XPath eignet sich ideal für die Selektion von Teilen eines XML-Dokumentes und wird genau aus diesem Grund auch für exakt diese Aufgabe sowohl in XSLT als auch in XQuery eingesetzt. Es ist mit XPath-Mitteln alleine aber nicht möglich, neue XML-Strukturen zu konstruieren. Genau an dieser Stelle setzen die in Kapitel 2.2.4 beschriebenen Möglichkei-ten zur Konstruktion eines Rückgabewertes in XQuery an. Daneben sind in XQuery noch eine Reihe weiterer Funktionen eingebaut worden, die man in XPath vergeblich sucht, wie z.B. umfangreiche Sortieroperationen oder Funktionen zur Behandlung von Datumsangaben.

XML-Schema

Zusammen mit der Veröffentlichung der ersten XML-Version 1.0 wurde auch eine Technik zur Definition von Dokument-Strukturen vorgestellt. Es handelte sich um die Document-Type-Definition-Sprache, die meist mit der Abkürzung DTD bezeichnet wird. Sinn einer solchen Sprache war es, Regeln zu definieren, die etwas über die Struktur von XML-Dokumenten aussagen, um denjenigen, die diese Dokumente erstellen müssen, eine Vorlage für ihre Arbeit zu geben.

Wie an vielen Stellen dieses Buches sei auch hier auf das Gegenstück in der relationalen SQL-Welt verwiesen: Über DDL (Data Definition Language)-Konstrukte lassen sich Objekte innerhalb von relationalen Datenbanken defi-nieren. Dies können beispielsweise Tabellen, Views oder Trigger sein. Allen Objekten ist gemeinsam, dass ihre Definition über entsprechende CREATE TABLE-, CREATE VIEW- oder CREATE TRIGGER-Skripte Regeln festlegen, die alle Daten erfüllen müssen, die in diesen Objekten gespeichert oder durch diese verarbeitet werden sollen. Diese Regeln können sowohl den Typ der Daten (Integer, String, …) als auch inhaltliche Vorschriften (Wertebereiche, Constraints, …) betreffen.

Page 35: XQuery. Eine praxisorientierte Einführung  GERMAN

Einführung

35

Nachteile von DTDs

Über eine DTD werden die zulässigen Element- und Attributtypen festgelegt. Alle XML-Dokumente, die auf der Basis dieser DTD erstellt wurden und dies durch einen entsprechenden Eintrag im Header verdeutlichen, können durch einen validierenden XML-Parser verifiziert werden. Dabei wird vom XML-Parser überprüft, ob es sich um ein gültiges Dokument handelt. Das Doku-ment ist gültig, wenn seine Inhalte den Regeln der DTD entsprechen.

DTDs werden in einer eigenen Syntax erstellt, sind also selber nicht in XML-Format. Während dieser „Nachteil“ noch zu verkraften wäre, stellt das sehr eingeschränkte Typkonzept von DTD einen Nachteil dar, der insbesondere in der Integration von XML- mit Datenbanktechnologien fast schon zum K.O.-Kriterium gegen den Einsatz von DTDs geworden ist.

Bei der Entwicklung der DTD-Technik stand ganz eindeutig die Dokumen-tenverarbeitung mit XML-Techniken im Vordergrund. Aus diesem Grund lassen sich über DTDs fast ausschließlich Textdatentypen mit einigen weni-gen Constraints darstellen. Spätestens dann, wenn auch numerische Datenty-pen ins Spiel kommen, stößt man mit DTDs sehr schnell an die Modellie-rungsgrenzen. Neben dem eingeschränkten Typkonzept sind DTDs noch durch folgende Nachteile gekennzeichnet:

• keine Unterstützung für Wiederverwendbarkeit, • keine Unterstützung von XML-Namensräumen, • keine Möglichkeit, das Typsystem zu erweitern. • Die Tatsache, dass DTDs selber nicht in XML-Syntax vorliegen, lässt

keine Validierung der DTDs durch XML-Validierungstechniken zu.

Insbesondere die Erweiterung des zugrunde liegenden Typkonzeptes war daher die Motivation für die Entwicklung einer fortgeschritteneren Modellie-rungssprache. Ergebnis dieser Entwicklungsarbeit ist XML-Schema.

Page 36: XQuery. Eine praxisorientierte Einführung  GERMAN

Standardisierung

36

XML-Schema-Typkonzept

Im Vergleich zum einfachen Typkonzept von DTDs wird über XML-Schemata3 eine Typhierarchie eingeführt. Dazu ist zunächst eine Reihe von Datentypen vordefiniert. Die folgende Auflistung enthält eine Auswahl der am häufigsten eingesetzten Datentypen. Abbildung 1.7 zeigt einen vollstän-digen Überblick über diese vordefinierten Datentypen inklusive ihrer Hierar-chie.

• boolean

• byte

• date

• decimal

• double

• float

• integer

• long

• short

• string

• time

• unsignedByte

• unsignedInt

• unsignedLong

• unsignedShort

Bereits an dieser Auswahl ist zu erkennen, dass über XML-Schemata neben einer Verarbeitung von dokumentenorientierten XML-Dateien, die meist noch mit den wenigen textorientierten Datentypen der DTDs möglich war, insbesondere auch eine Verarbeitung von datenorientierten XML-Dateien ermöglicht wird. Auch der Bezug zu den analogen Datentypen innerhalb der Datenbankwelt ist zu erkennen.

3 Die korrekte Bezeichnung lautet eigentlich XML-Schema-Definition. In der Litera-tur wird aber meist die Kurzform XML-Schema verwendet, die daher auch in diesem Buch zum Einsatz kommt.

Page 37: XQuery. Eine praxisorientierte Einführung  GERMAN

Einführung

37

Abbildung 1.7: Vordefinierte XML-Schema-Datentypen (Quelle: [XSD])

Auf der Basis dieser vordefinierten Datentypen können nun eigene Datenty-pen definiert werden. Diese eigenen Datentypen können wiederum in zwei verschiedene Gruppen eingeteilt werden:

• einfache Datentypen (simple types) • komplexe Datentypen (complex types)

Bei der Definition einfacher Datentypen können u.a. die folgenden Eigen-schaften festgelegt werden:

• Wertebereich: Definiert, welche Werte des zugrunde liegenden Daten-typs erlaubt sind.

• Repräsentationsraum: Definiert die Menge der Literale für die Werte aus dem Wertebereich. Während meist jeder Wert genau ein Literal, also ei-

Page 38: XQuery. Eine praxisorientierte Einführung  GERMAN

Standardisierung

38

ne Möglichkeit zur Darstellung besitzt, kann es bei bestimmten Datenty-pen sinnvoll sein, mehrere Darstellungsarten zuzulassen, beispielsweise bei float-Werten eine Angabe darüber, ob der Wert „Eintausend“ so-wohl als 1000 als auch als 1.0E3 dargestellt werden kann.

• Aufzählung erlaubter Werte (enumeration) • Unter- und Obergrenzen für den Wertebereich • Längenbeschränkung für Zeichenketten und decimal-Werte • Kardinalität

Auch an dieser Stelle sei wieder auf die analogen Möglichkeiten hingewie-sen, bei der Definition relationaler Speicherkonstrukte entsprechende Con-straints beispielsweise für Datenbankspalten zu modellieren.

Innerhalb von XML-Dokumenten werden einfache Datentypen meist als Grundlage für Attributwerte und Elementinhalte eingesetzt. XML-Elemente können aber auch eine komplexere Struktur haben. Sie können eine Vielzahl von Attributen sowie verschachtelte Unterelemente enthalten. Als Datentyp solcher komplexer XML-Elemente reichen die einfachen Datentypen nicht aus. Benötigt werden an dieser Stelle stattdessen Kombinationen von einfa-chen Datentypen sowie Definitionsmöglichkeiten für Constraints innerhalb der Unterelemente eines Datentyps.

Diese Möglichkeiten bieten die komplexen Datentypen (complex types). Dabei lassen sich folgende Erweiterungen bzw. Beschränkungen gegenüber einfachen und vordefinierten Datentypen festlegen:

• Hinzufügen von Attributen • Hinzufügen von Unterelementen, die maximal ein Mal vorkommen dür-

fen, bei denen aber die Reihenfolge nicht festgelegt ist (all) • Definition einer Menge von Unterelementen mit der Einschränkung, dass

nur eines dieser Unterelemente wirklich auftreten darf (choice) • Hinzufügen von Unterelementen in einer festgelegten Reihenfolge (se-

quence)

Wie bereits erwähnt, sind XML-Schema-Definitionen die Grundlage für das Typsystem von XQuery. XQuery kann zwar auch ohne definierte Datentypen arbeiten, nämlich immer dann, wenn Input-XML-Daten verarbeitet werden sollen, die ebenfalls ohne Typinformationen vorliegen. Wenn aber bestimmte

Page 39: XQuery. Eine praxisorientierte Einführung  GERMAN

Einführung

39

Datentypen verarbeitet werden sollen, dann kommt das XQuery-Typkonzept ins Spiel, und dieses basiert auf XML-Schema. Wie in Kapitel 2.4 noch aus-führlich erläutert wird, bilden auch in XQuery vordefinierte Datentypen die Basis für das Typkonzept. Diese vordefinierten XQuery-Datentypen setzen sich aus den 46 vordefinierten XML-Schema-Datentypen (s. Abbildung 1.7) sowie 13 weiteren in XQuery eingeführten Datentypen zusammen. Zusätzlich gibt es die Möglichkeit, in XQuery eigene Datentypen durch XML-Schema-Definitionen festzulegen und durch entsprechende Import-Anweisungen innerhalb von XQuery-Skripten einzubinden. Beispiele zu XML-Schema-Definitionen finden sich in Kapitel 2.4 dieses Buches, wo solche selbst defi-nierten Datentypen angelegt und eingesetzt werden.

1.4 Zusammenfassung Dieses einführende Kapitel sollte Ihnen einen ersten Überblick über XQuery geben. Bewusst wurden dabei noch keine Sourcecode-Beispiele eingesetzt. Dies wird im folgenden Kapitel bei der Vorstellung der einzelnen XQuery-Sprachbestandteile nachgeholt.

Für eine erste Einschätzung der Potenziale von XQuery wurden die verwand-ten XML-Standards XPath, XML-Schema und XSLT kurz vorgestellt. Dabei wurden einerseits die Gemeinsamkeiten dieser Standards herausgestellt, ins-besondere die enge Verknüpfung von XPath und XQuery, die u.a. durch die gemeinsame Arbeit der beiden W3C-Arbeitsgruppen bei der Entwicklung der neuesten Versionen XPath 2.0 und XQuery 1.0 entstanden ist und die sich vor allem darin bemerkbar macht, dass diese beiden Standard-Versionen auf ein gemeinsames Datenmodell zurückgreifen können. Andererseits wurde aber auch schon auf die Unterschiede dieser Standards hingewiesen, die die Grundlage für die Entscheidung waren, eine neue Abfragesprache für XML zu entwerfen, anstatt bestehende Standards entsprechend zu erweitern.

Im folgenden Kapitel werden nun die einzelnen Bestandteile der XQuery-Sprache anhand von Beispielen vorgestellt. Dabei steht zunächst die grundle-gende Syntax im Vordergrund. Im Verlauf des Kapitels werden die verwen-deten Beispiele aber auch jeweils so erweitert, dass Tipps für einen sinnvol-len Einsatz der einzelnen Bestandteile gegeben werden können, d.h. für einen Programmierstil, der einerseits die hierarchische Struktur der zu verarbeiten-

Page 40: XQuery. Eine praxisorientierte Einführung  GERMAN

Zusammenfassung

40

den XML-Daten berücksichtigt, andererseits auch eine effiziente Abarbeitung der Abfragen ermöglicht.

Wie bereits erwähnt wurde, zählt XQuery aber zu den deklarativen Sprachen. Dabei legt der Programmierer nur fest, welches Ergebnis er erwartet, nicht wie dieses Ergebnis erreicht werden soll. Diese Vorgehensweise unterschei-det sich grundlegend von der bei prozeduralen Sprachen, bei denen der Ent-wickler auch den Weg implementiert, auf dem das Ergebnis erreicht werden soll. Eine entscheidende Rolle insbesondere im Hinblick auf die Performance der implementierten Abfragen spielt also auch bei XQuery die verwendete XQuery-Implementierung, deren Aufgabe darin besteht, das XQuery-Skript gemäß den XQuery-Regeln auszuführen. Kapitel 3 stellt daher einige bereits verfügbare Implementierungen vor, mit denen die Beispiele aus dem folgen-den Kapitel getestet werden können. Nochmals sei darauf hingewiesen, dass der XQuery-Standard zum Zeitpunkt der Erstellung dieses Buches noch nicht endgültig verabschiedet worden ist. Kleinere Änderungen am Sprachumfang sind zwar aufgrund der diesem Buch zugrunde liegenden recht stabilen Ver-sion aus dem November 2003 unwahrscheinlich, allerdings nicht vollständig auszuschließen. Sollten beim Testen der Beispiele dieses Buches mit einer neueren XQuery-Version Fehler auftreten, so können diese eventuell auf solche nachträglichen Änderungen am Standard zurückzuführen sein. In diesem Fall lohnt sich ein Blick auf die Webseite zu diesem Buch (http://www.entwickler.com/buecher/xquery), auf der auch die im folgenden Kapitel behandelten Beispiele zum Download zur Verfügung gestellt werden.

Page 41: XQuery. Eine praxisorientierte Einführung  GERMAN

Sprachbestandteile

41

2 Sprachbestandteile

Nachdem im letzten Kapitel einige allgemeine Aspekte zum Thema XQuery behandelt wurden, soll in diesem Hauptkapitel des Buches nun die Sprache selber vorgestellt werden. Nach dem nahezu Sourcecode-freien ersten Kapitel ist dieses zweite Kapitel ausschließlich anwendungsorientiert, d.h. die einzel-nen Sprachbestandteile werden anhand kleinerer Beispiele beschrieben.

Sie können dieses Kapitel auf zwei verschiedene Arten durcharbeiten. Falls Sie ein reines Buchstudium bevorzugen, weil Ihnen beispielsweise kein Rechner während der Durcharbeitung der Abschnitte zur Verfügung steht, ist dies problemlos möglich. Alle Inputdaten, XQuery-Skripte und Ergebnisda-teien sind in den folgenden Kapiteln abgedruckt, sodass Ihnen alle benötigten Informationen auch ohne direkten Zugriff auf einen Rechner zur Verfügung stehen.

Sie können die im Folgenden beschriebenen Beispiele aber auch selber am Rechner ausführen. Die dazu benötigten Daten (Inputdokumente und XQuery-Skripte) stehen auf der Webseite dieses Buches zum Download zur Verfügung (http://www.entwickler.com/buecher/xquery). Der Vorteil dieser Vorgehensweise besteht darin, dass Sie die Beispiele dann auch direkt als Ausgangspunkt für ein eigenständiges Experimentieren mit der neuen Spra-che nutzen können.

2.1 Beispieldaten Als Inputdaten für die ersten einführenden Beispiele in den folgenden Ab-schnitten dient die folgende XML-Datei mit einem Auszug aus einer Biblio-theksverwaltung. Sie wird in den Beispielen über den Dateinamen bib.xml referenziert.

Page 42: XQuery. Eine praxisorientierte Einführung  GERMAN

Beispieldaten

42

<?xml version="1.0" encoding="ISO-8859-1"?>

<bib>

<book year="2004">

<title>Java Persistenz Strategien</title>

<author>

<last>Holubek</last>

<first>Andreas</first>

</author>

<author>

<last>Jansen</last>

<first>Rudolf</first>

</author>

<author>

<last>Munsky</last>

<first>Robert</first>

</author>

<author>

<last>Wolff</last>

<first>Eberhard</first>

</author>

<publisher>Software u. Support</publisher>

<price>39.90</price>

</book>

<book year="2003">

<title>Oracle, Java, XML</title>

<author>

<last>Jansen</last>

<first>Rudolf</first>

</author>

<publisher>Software u. Support</publisher>

<price>39.90</price>

</book>

<book year="2002">

<title>Tomcat 4x</title>

<author>

<last>Holubek</last>

Page 43: XQuery. Eine praxisorientierte Einführung  GERMAN

Sprachbestandteile

43

<first>Andreas</first>

</author>

<author>

<last>Poeschmann</last>

<first>Thomas</first>

</author>

<author>

<last>Roewekamp</last>

<first>Lars</first>

</author>

<author>

<last>Rossbach</last>

<first>Peter</first>

</author>

<author>

<last>Tabatt</last>

<first>Peter</first>

</author>

<publisher>Software u. Support</publisher>

<price>24.90</price>

</book>

<book year="1999">

<title>Refactoring</title>

<author>

<last>Fowler</last>

<first>Martin</first>

</author>

<publisher>Addison-Wesley</publisher>

<price>49.90</price>

</book>

</bib>

Die Beispiele, die Join-Bedingungen über mehrere Dokumente illustrieren sollen, arbeiten neben dieser bib.xml-Datei noch auf folgender adress.xml-Datei, die Adressen einiger Autoren aus der Bibliotheks-Datei enthält:

Page 44: XQuery. Eine praxisorientierte Einführung  GERMAN

FLWOR-Ausdrücke

44

<?xml version="1.0" encoding="ISO-8859-1"?>

<addresses>

<address>

<last>Holubek</last>

<first>Andreas</first>

<city>Dresden</city>

</address>

<address>

<last>Jansen</last>

<first>Rudolf</first>

<city>Aachen</city>

</address>

<address>

<last>Munsky</last>

<first>Robert</first>

<city>Dresden</city>

</address>

<address>

<last>Wolff</last>

<first>Eberhard</first>

<city>Hamburg</city>

</address>

</addresses>

2.2 FLWOR-Ausdrücke Als erste Einstimmung in die XQuery-Syntax diene folgende XQuery-Abfrage:

for $b in doc("input/bib.xml")/bib/book

where $b/@year = 2002

return

<buch>

{ $b/title }

</buch>

Page 45: XQuery. Eine praxisorientierte Einführung  GERMAN

Sprachbestandteile

45

Dieses erste Beispiel beinhaltet bereits einige der wichtigsten Bestandteile von XQuery-Abfragen. Ein XQuery-Ausdruck wird häufig auch als FLWOR-Ausdruck4 bezeichnet, wobei die einzelnen Buchstaben die Bestandteile eines Ausdruckes wie folgt kennzeichnen:

• For: Klausel zur Variablenbindung. Vergleichbar mit entsprechenden For-Schleifen in den bekannten Programmiersprachen wird eine Iteration über alle in der For-Klausel gebundenen Input-Werte durchgeführt.

• Let: Klausel zur einfachen Variablenbindung. Die Variable wird einma-lig an einen Wert oder eine Menge von Werten gebunden. Eine Iteration über Einzelwerte findet im Gegensatz zur For-Klausel nicht statt. Obiges Beispiel enthält keine Let-Klausel. Weiter unten finden sich aber passen-de Beispiele. Jeder XQuery-Ausdruck muss mindestens eine For-Klausel oder mindestens eine Let-Klausel beinhalten.

• Where: (optionaler) Ausdruck zur Filterung. Vergleichbar mit den ent-sprechenden Where-Klauseln in SQL-Ausdrücken wird über einen Whe-re-Ausdruck diejenige Teilmenge der Inputdaten – also der über For- und/oder Let-Ausdrücke spezifizierten Daten – festgelegt, die bei der Konstruktion der Ergebnismenge verwendet werden soll.

• Order By: (optionaler) Ausdruck zur Sortierung der Daten, die bei der Filterung gemäß der Where-Klausel ermittelt wurden. Kapitel 2.2.3 ent-hält eine genauere Beschreibung der Möglichkeiten zur Sortierung in-nerhalb von XQuery-Ausdrücken.

• Return: Konstruktion des Rückgabewertes für alle Daten, die die Where-Klausel erfüllen.

Zerlegt man den obigen Ausdruck in seine Einzelbestandteile, so haben diese folgende Aufgaben:

for $b in doc("input/bib.xml")/bib/book

Über die For-Klausel wird eine Schleife erzeugt, die für jeden Wert einmal durchlaufen wird. Die Menge dieser Werte wird durch den in der For-Klausel angegebenen Ausdruck doc("input/bib.xml")/bib/book erzeugt. Die-ser Ausdruck wiederum lässt sich in zwei Teile aufteilen: 4 ausgesprochen wie „flower“ in der englischen Sprache

Page 46: XQuery. Eine praxisorientierte Einführung  GERMAN

FLWOR-Ausdrücke

46

• Einlesen der Inputdaten aus einer externen Quelle. In diesem Beispiel werden die Daten aus der im Verzeichnis input liegenden Datei mit dem Namen bib.xml (s. Kapitel 2.1) eingelesen. Die Verzeichnisangaben selber sind implementierungsspezifisch, d.h. es hängt von der eingesetz-ten XQuery-Implementierung ab, wo der relative Pfad input gesucht wird. Manche Implementierungen erlauben auch absolute Pfadangaben. Die zum Einlesen der externen Daten benutzte Funktion doc ist eine vor-definierte XQuery-Funktion, der über einen URI-Parameter ein XML-Dokument übergeben wird und deren Rückgabewert der Wurzelknoten der Baumdarstellung dieses XML-Dokumentes ist.

• Der zweite Teil besteht aus einem XPath-Ausdruck, über den die inner-halb der For-Schleife zu verarbeitende Knotenmenge des Inputdokumen-tes selektiert werden kann. In obigem Beispiel wird also der XPath-Ausdruck /bib/book auf den Rückgabewert der doc-Funktion ange-wendet, d.h. es werden alle book-Unterelemente von bib-Elementen des Wurzelknotens der Baumdarstellung von bib.xml selektiert. Wie aus der in Kapitel 2.1 angegebenen Datei ersichtlich ist, handelt es sich also um eine Menge von insgesamt vier book-Elementen. Die For-Schleife wird also vier Mal durchlaufen.

Aus dieser vierelementigen Menge werden nun über die folgende Where-Klausel diejenigen Werte ausgefiltert, die für die Konstruktion der Ergebnis-menge verwendet werden sollen.

where $b/@year = 2002

Auch hier kommt wieder XPath zum Einsatz. Die Variable $b enthält bei jeder Iteration einen Teilbaum des Inputdokumentes, in diesem Fall jeweils ein book-Element inklusive aller Unterelemente. Aus diesem Teilbaum wird über den XPath-Ausdruck @year5 das Attribut year selektiert. Die Filterung über diese Where-Klausel bewirkt also, dass nur diejenigen Bücher, die ge-mäß dem Attribut @year ein Erscheinungsjahr 2002 besitzen, für die Kon-struktion der Ergebnismenge verwendet werden.

5 Wie in Kapitel 1.3.4 beschrieben, ist das @-Zeichen die Abkürzung für die Achse attribute:: innerhalb eines XPath-Ausdruckes.

Page 47: XQuery. Eine praxisorientierte Einführung  GERMAN

Sprachbestandteile

47

Das Ergebnis des XQuery-Ausdrucks wird schließlich über die Return-Klausel erzeugt, die für alle eingelesenen Bestandteile des Input-Dokumen-tes, die die Bedingung der where-Klasuel erfüllen, also in diesem Fall nur für das eine ausgewählte book-Element, aufgerufen wird.

return

<buch>

{ $b/title }

</buch>

Rückgabewert eines XQuery-Ausdruckes ist immer ein XML-Dokument. Dieses wird durch statische Bestandteile – in diesem Beispiel durch die ex-plizit in der Return-Klausel angegebenen öffnenden und schließenden Tags <buch> und </buch> – sowie über durch Variable gekennzeichnete dynami-sche Bestandteile erzeugt. Hier im Beispiel wird aus allen ausgefilterten book-Elementen das title-Unterelement ausgewählt.

Die gesamte Abfrage liefert also folgendes Ergebnis:

<buch>

<title>Tomcat 4x</title>

</buch>

Ein XQuery-Ausdruck kann auch innerhalb von statischen XML-Konstrukten eingebaut werden:

<buchliste>

{

for $b in doc("input/bib.xml")/bib/book

where $b/@year = 2002

return

<buch>

{ $b/title }

</buch>

}

</buchliste>

Page 48: XQuery. Eine praxisorientierte Einführung  GERMAN

FLWOR-Ausdrücke

48

Hier wird durch die geschweiften Klammern { und } der Block gekennzeich-net, der von der XQuery-Engine ausgewertet werden soll. Das Ergebnis dieses Ausdruckes lautet also:

<buchliste>

<buch>

<title>Tomcat 4x</title>

</buch>

</buchliste>

Auch eine Verschachtelung von XQuery-Ausdrücken ist möglich, wie fol-gendes Beispiel zeigt:

<autorenliste>

{

for $authorname in

distinct-values(doc("input/bib.xml")//author/last)

return

<autor name="{$authorname}">

{

for $b in doc("input/bib.xml")/bib/book

where $b/author/last = $authorname

return $b/title

}

</autor>

}

</autorenliste>

Hier wird innerhalb der Return-Klausel ein weiterer XQuery-Ausdruck ein-gesetzt. Dies ist möglich, da der Rückgabewert eines XQuery-Ausdruckes in XML-Format vorliegt und daher unmittelbar als Bestandteil der Return-Klausel verwendet werden kann.

Während die in Kapitel 2.1 angegebene Inputdatei bib.xml nach Büchern geordnet ist, d.h. zu jedem Buch sind alle Autoren angegeben, bewirkt obiger XQuery-Ausdruck die entgegengesetzte Ordnung: Aufgelistet werden alle Autoren zusammen mit den Büchern, an denen sie mitgearbeitet haben.

Page 49: XQuery. Eine praxisorientierte Einführung  GERMAN

Sprachbestandteile

49

Dazu werden zunächst alle Autoren bzw. genauer gesagt ihre Nachnamen über den XQuery-Ausdruck //author/last6 ausgewählt. Die Funktion distinct-values bewirkt eine Elimination von Duplikaten, d.h. jeder Autorenname wird nur genau einmal selektiert. Bei der Funktion distinct-values handelt es sich um eine vordefinierte XQuery-Funktion, die in Kapi-tel 2.5.2 behandelt wird.

Zu diesen Autoren werden nun über den inneren XQuery-Ausdruck alle Bü-cher gesucht, bei denen sie in einem der author-Elemente als Autor einge-tragen sind. Ergebnis des Gesamtausdrucks ist also das folgende XML-Konstrukt:

<autorenliste>

<autor name="Holubek">

<title>Java Persistenz Strategien</title>

<title>Tomcat 4x</title>

</autor>

<autor name="Jansen">

<title>Java Persistenz Strategien</title>

<title>Oracle, Java, XML</title>

</autor>

<autor name="Munsky">

<title>Java Persistenz Strategien</title>

</autor>

<autor name="Wolff">

<title>Java Persistenz Strategien</title>

</autor>

<autor name="Poeschmann">

<title>Tomcat 4x</title>

</autor>

<autor name="Roewekamp">

<title>Tomcat 4x</title>

</autor>

6 Auch hier wurde wieder die XPath-Kurznotation angewendet. Die vollständige Notation lautet: descendant-or-self::author/child::last

Page 50: XQuery. Eine praxisorientierte Einführung  GERMAN

FLWOR-Ausdrücke

50

<autor name="Rossbach">

<title>Tomcat 4x</title>

</autor>

<autor name="Tabatt">

<title>Tomcat 4x</title>

</autor>

<autor name="Fowler">

<title>Refactoring</title>

</autor>

</autorenliste>

In den folgenden Abschnitten werden nun einige Besonderheiten zu den einzelnen Bestandteilen der FLWOR-Ausdrücke beschrieben.

2.2.1 Variablenbindung Jeder XQuery-Ausdruck muss mindestens eine For- oder mindestens eine Let-Klausel enthalten. Beide Klauseln dienen hauptsächlich zur Einbindung der Inputdaten. Sie unterscheiden sich u.a. dadurch, dass über eine For-Klau-sel eine Iteration über eine Menge von Inputdaten definiert wird, während über eine Let-Klausel eine einmalige Variablenbindung vorgenommen wer-den kann.

Wichtig für das Verständnis der Variablenbindung und damit auch für die grundlegenden Verarbeitungsschritte in XQuery-Ausdrücken ist der Tupel-Begriff. Jeder Bestandteil der FLWOR-Ausdrücke, die in diesem Kapitel vorgestellt werden, arbeitet auf Tupeln, die aus Inputdaten erzeugt werden. Für diese Erzeugung der Tupel sind die For- und Let-Klauseln zuständig. Die Beispiele in den folgenden Abschnitten zeigen die grundlegenden Unter-schiede bei der Erzeugung der Tupel.

For

Das erste Beispiel zeigt die standardmäßige Vorgehensweise bei der Erzeu-gung einer Iteration mittels einer For-Klausel. Hier werden die Inputdaten nicht wie in den bisherigen Beispielen aus einer externen Datei eingelesen, sondern explizit in der For-Klausel spezifiziert.

Page 51: XQuery. Eine praxisorientierte Einführung  GERMAN

Sprachbestandteile

51

for $i in ("a","b","c")

return

<value>{ $i }</value>

Über den Ausdruck ("a","b","c") wird eine Folge von String-Werten erzeugt. Generell kann jeder gültige XQuery-Ausdruck an dieser Stelle in einer For-Klausel angegeben werden. Der Ausdruck wird als Sequenz von Einzelwerten ausgewertet. Jeder dieser Einzelwerte bildet dann jeweils in einem eigenen Iterationsschritt das vom Rest des FLWOR-Ausdruckes zu bearbeitende Tupel. Das Ergebnis dieses ersten Beispieles sieht daher wie folgt aus:

<value>a</value>

<value>b</value>

<value>c</value>

Optional kann über eine Positionsvariable und das Schlüsselwort at auch die Position des aktuell in Bearbeitung befindlichen Tupels innerhalb der Input-Sequenz in die Ausgabe integriert werden. Zur Illustration wird das obige Beispiel wie folgt erweitert:

for $i at $pos in ("a", "b", "c")

return

<value position="{$pos}">{ $i }</value>

In diesem Fall sieht die Ausgabe wie folgt aus:

<value position="1">a</value>

<value position="2">b</value>

<value position="3">c</value>

Let

Im Gegensatz zur For-Klausel bindet die Let-Klasuel den gesamten Ausdruck einmalig an die angegebene Variable. Der Ausdruck

Page 52: XQuery. Eine praxisorientierte Einführung  GERMAN

FLWOR-Ausdrücke

52

let $i := ("a","b","c")

return

<value>{ $i }</value>

liefert als nur ein <value>-Element als Ergebnis, das dann aber den kom-pletten über die Let-Klausel eingelesenen Ausdruck enthält:

<value>abc</value>

Die folgende Kombination von For- und Let-Klausel illustriert nochmals den Unterschied:

for $i in ("a","b","c")

let $j := ("a","b","c")

return

<value><i>{ $i }</i><j>{ $j }</j></value>

Ergebnis sind diesmal wieder drei <value>-Elemente, da ja durch Einsatz der For-Klausel wieder eine Iteration über die drei aus der in der For-Klausel angegebenen Sequenz erzeugten Tupel durchlaufen wird:

<value>

<i>a</i>

<j>abc</j>

</value>

<value>

<i>b</i>

<j>abc</j>

</value>

<value>

<i>c</i>

<j>abc</j>

</value>

Da in diesem Beispiel innerhalb der Let-Klausel kein Bezug auf die in der For-Klausel belegte Variable i genommen wird, hätte dasselbe Ergebnis auch durch Vertauschen der For- und Let-Klausel erreicht werden können:

Page 53: XQuery. Eine praxisorientierte Einführung  GERMAN

Sprachbestandteile

53

let $j := ("a","b","c")

for $i in ("a","b","c")

return

<value><i>{ $i }</i><j>{ $j }</j></value>

In einer For-Klausel können auch mehrere Variable angegeben und mit Wer-ten belegt werden:

for $i in …,

$j in …

In diesen Fällen wird das kartesische Produkt gebildet, d.h. jede mögliche Kombination von Werten für die Variablen i und j wird gebildet und für jede dieser Kombinationen wird der Rest des FLWOR-Ausdruckes durchlau-fen. Beispiele dazu sind in den Kapiteln 2.3.3 und 2.7 zu finden.

2.2.2 Filterung Eine Where-Klausel kann innerhalb eines FLWOR-Ausdruckes zur Filterung eingesetzt werden. Im Gegensatz zu den For- und Let-Klauseln, von denen immer mindestens eine zur Variablenbindung vorhanden sein muss, sowie der ebenfalls immer benötigten Return-Klausel ist eine Where-Klausel optio-nal. Sie dient dazu, aus den über die For- und/oder Let-Klauseln konstruier-ten Tupeln diejenigen auszufiltern, die nicht bei der Konstruktion des Ergeb-nisses in der Return-Klausel verwendet werden sollen.

Innerhalb der Where-Klauseln können beliebige Ausdrücke angegeben wer-den, die einen Boolean-Wert als Ergebnis liefern. Dies kann ein einfacher Vergleichs-Ausdruck sein, wie schon in den einführenden Beispielen ver-wendet:

for $b in doc("input/bib.xml")/bib/book

where $b/@year = 2002

return

Page 54: XQuery. Eine praxisorientierte Einführung  GERMAN

FLWOR-Ausdrücke

54

Weitere Erläuterungen zu den zur Verfügung stehenden Vergleichsoperato-ren enthält Kapitel 2.3.3. Es können aber auch Quantoren eingesetzt werden, die eine detailliertere Untersuchung des aktuellen Tupels ermöglichen. Be-steht ein solches Tupel nicht aus einem atomaren Wert, sondern aus einer Sequenz, so kann über die beiden Quantoren some und every überprüft werden, ob mindestens einer (some) der Werte in der Sequenz bzw. alle (every) Werte der Sequenz eine angegebene Bedingung erfüllen.

Some

In der folgenden Abfrage wird über die For-Klausel eine Iteration über alle <book>-Einträge der Inputdatei erzeugt. Diese <book>-Einträge sind keine atomaren Werte, sondern Elemente, die wiederum Unterelemente besitzen. Soll nun innerhalb dieser Unterelemente eine Bedingung überprüft werden, die nur in mindestens einem dieser Unterelemente erfüllt sein muss, so kann dies wie folgt spezifiziert werden.

<andreas-buecher>

{

for $b in doc("input/bib.xml")//book

where some $a in $b/author

satisfies ($a/first="Andreas")

return

$b/title

}

</andreas-buecher>

Die Abfrage sucht also nach den Titeln aller Bücher in der Inputdatei, bei denen mindestens ein Autor den Vornamen Andreas trägt. Das Ergebnis lautet:

<andreas-buecher>

<title>Java Persistenz Strategien</title>

<title>Tomcat 4x</title>

</andreas-buecher>

Page 55: XQuery. Eine praxisorientierte Einführung  GERMAN

Sprachbestandteile

55

Every

Soll die im vorigen Abschnitt angegebene Abfrage nun so erweitert werden, dass die Titel derjenigen Bücher ermittelt werden sollen, bei denen alle Auto-ren den Vornamen Andreas besitzen, so muss das Schlüsselwort some durch das Schlüsselwort every ersetzt werden:

<andreas-buecher>

{

for $b in doc("input/bib.xml")//book

where every $a in $b/author

satisfies ($a/first="Andreas")

return

$b/title

}

</andreas-buecher>

Da keines der Bücher in der Inputdatei diese Bedingung erfüllt, sieht das Ergebnis dieser Abfrage wie folgt aus:

<andreas-buecher/>

Zu beachten bei der Verwendung von every ist der im folgenden Beispiel durch einen Tippfehler erzwungene Umgang mit leeren Werten:

<andreas-buecher>

{

for $b in doc("input/bib.xml")//book

where every $a in $b/autor

satisfies ($a/first="Andreas")

return

$b/title

}

</andreas-buecher>

Der XPath-Ausdruck

$b/autor

Page 56: XQuery. Eine praxisorientierte Einführung  GERMAN

FLWOR-Ausdrücke

56

liefert eine Sequenz der Länge 0, da es innerhalb der <book>-Elemente kein Unterelement mit Namen autor gibt. Als Folge dessen sieht das Ergebnis dieser Abfrage aber nun wie folgt aus:

<andreas-buecher>

<title>Java Persistenz Strategien</title>

<title>Oracle, Java, XML</title>

<title>Tomcat 4x</title>

<title>Refactoring</title>

</andreas-buecher>

Der Grund für dieses wahrscheinlich nicht beabsichtige Ergebnis liegt darin, dass die Anwendung des Quantors every auf eine leere Sequenz immer den Boolean-Wert true ergibt. Dies kann man so begründen, dass es ja keinen Eintrag in der (leeren) Sequenz gibt, der die Bedingung nicht erfüllt. Also erfüllen alle Einträge die Bedingung, also liefert every hier den Wert true für alle durchlaufenen <book>-Einträge, sodass keiner dieser Einträge ausge-filtert wird und alle Titel in der Return-Klausel ausgegeben werden.

Der some-Quantor besitzt hier ein anderes Verhalten: some angewendet auf eine leere Sequenz liefert den Wert false, sodass ein identischer Tippfehler (autor anstelle author im XPath-Ausdruck) im Beispiel aus dem vorherge-henden Abschnitt

<andreas-buecher>

{

for $b in doc("input/bib.xml")//book

where some $a in $b/autor

satisfies ($a/first="Andreas")

return

$b/title

}

</andreas-buecher>

das erwartete Ergebnis

<andreas-buecher/>

Page 57: XQuery. Eine praxisorientierte Einführung  GERMAN

Sprachbestandteile

57

liefert, da hier kein Eintrag in der (leeren) Sequenz der Variablen a gefunden wird, der die in der satisfies-Klausel angegebene Bedingung erfüllt.

2.2.3 Sortierung Soll bei der Konstruktion des Abfrageergebnisses in der Return-Klausel nicht die bei der Variablenbindung über die For- und/oder Let-Klauseln spezifi-zierte Reihenfolge verwendet werden, so kann eine benutzerdefinierte Rei-henfolge über eine optionale Order-By-Klausel innerhalb eines FLWOR-Ausdrucks angegeben werden. Im folgenden Beispiel werden die auszuge-benden Buchtitel nach Preisangabe im <price>-Unterelement der <book>-Elemente sortiert.

for $b in doc("input/bib.xml")/bib/book

order by $b/price

return

<book>

{ $b/title }

{ $b/price }

</book>

In einer Order-By-Klausel können auch mehrere Sortierkriterien angegeben werden, die in der angegebenen Reihenfolge verarbeitet werden:

order by $b/price, $b/title

Das Ergebnis dieser Abfrage lautet

<book>

<title>Tomcat 4x</title>

<price>24.90</price>

</book>

<book>

<title>Java Persistenz Strategien</title>

<price>39.90</price>

</book>

Page 58: XQuery. Eine praxisorientierte Einführung  GERMAN

FLWOR-Ausdrücke

58

<book>

<title>Oracle, Java, XML</title>

<price>39.90</price>

</book>

<book>

<title>Refactoring</title>

<price>49.90</price>

</book>

Dieses Ergebnis ist allerdings nur zufällig korrekt. Der Grund liegt in einer ungenauen Angabe innerhalb der Order-By-Klausel

order by $b/price

sowie den eingebauten Regeln im XQuery-Typsystem. Wie in Kapitel 2.4 noch detailliert beschrieben wird, hat in XQuery jeder Knoten einen so ge-nannten „typed-value“. Dieser kann durch eine XML-Schema-Definition angegeben werden. Liegt eine solche XML-Schema-Definition nicht vor, dann werden Sortieroperationen gemäß der lexikografischen Sortierung durchgeführt, d.h. es werden String-Sortierverfahren durchgeführt.

Was das bedeutet, wird offensichtlich, wenn man in den zugrunde liegenden Inputdaten der Datei bib.xml den Preis des „Refactoring“-Buches von 49,90 auf 149,90 erhöht und obige Abfrage nochmals durchführt. Das Ergebnis lautet in diesem Fall:

<book>

<title>Refactoring</title>

<price>149.90</price>

</book>

<book>

<title>Tomcat 4x</title>

<price>24.90</price>

</book>

<book>

<title>Java Persistenz Strategien</title>

<price>39.90</price>

</book>

Page 59: XQuery. Eine praxisorientierte Einführung  GERMAN

Sprachbestandteile

59

<book>

<title>Oracle, Java, XML</title>

<price>39.90</price>

</book>

Da die Zeichenkette „149.90“ gemäß der lexikografischen Sortierung vor den Zeichenketten „24.90“ und „39.90“ landet, ergibt sich die nicht beabsichtigte Sortierung. Das Ergebnis der Abfrage auf den ursprünglichen Inputdaten war also nur deshalb zufällig richtig, weil alle Preisangaben dieselbe Stringlänge hatten und daher der Unterschied zwischen der lexikografischen und der numerischen Sortierung keine Auswirkungen hatte.

Das Problem lässt sich umgehen, indem entweder anhand einer XML-Schema-Definition ein numerischer Datentyp für das <price>-Element definiert wird oder durch Einsatz einer expliziten Typ-Casting-Operation innerhalb der Order-By-Klausel:

for $b in doc("input/bib.xml")/bib/book

order by xs:decimal($b/price)

return

<book>

{ $b/title }

{ $b/price }

</book>

Die zu sortierenden Preisangaben werden in diesem Fall gemäß den numeri-schen Sortierregeln des Datentyps decimal verarbeitet.

Wie aus den SQL-Sortierklauseln bereits bekannt, kann auch in den Order-By-Klauseln von XQuery die Sortierreihenfolge (aufsteigend oder abstei-gend) festgelegt werden. Defaultmäßig erfolgt eine aufsteigende Sortierung, die über das Schlüsselwort ascending angegeben werden kann bzw. bei Nicht-Angabe wie im obigen Beispiel automatisch verwendet wird. Eine absteigende Sortierung kann durch den Zusatz descending wie folgt er-reicht werden:

Page 60: XQuery. Eine praxisorientierte Einführung  GERMAN

FLWOR-Ausdrücke

60

for $b in doc("input/bib.xml")/bib/book

order by $b/price descending

return

<book>

{ $b/title }

{ $b/price }

</book>

Weitere optionale Bestandteile einer Order-By-Klausel sind die folgenden:

• empty least / empty greatest: Angaben zur Behandlung von NULL-Werten innerhalb von Sortieroperationen. Die Behandlung von NULL-Werten, also die Frage, ob Tupel, bei denen das in der Order-By-Klausel angegebene Element keinen Wert hat, an den Anfang oder das Ende der Sortierreihenfolge gesetzt werden, ist ohne die Angabe von empty least oder empty greatest implementierungsabhängig. Wer sich an dieser Stelle also nicht in die Abhängigkeit der eingesetzten XQuery-Implementierung (s. Kapitel 3) begeben will, muss explizit an-geben, ob NULL-Werte bei Vergleich mit NOT-NULL-Werten als grö-ßer oder als kleiner klassifiziert werden sollen.

• stable: Angaben zur Behandlung von Werten, bei denen das angege-bene Sortierkriterium keine Unterscheidung und damit auch keine defi-nierte Reihenfolge festgelegt hat. Wie bei den NULL-Werten ist auch in diesen Fällen ohne die Angabe von stable die generierte Reihenfolge implementierungsabhängig. Die Angabe von stable erzwingt dagegen in diesen Fällen eine Einhaltung der Dokumentenreihenfolge, d.h. der Reihenfolge, in der die Werte in den Inputdaten aufgeführt sind.

Die folgende Order-By-Klausel sortiert also gemäß der Preisangabe im Ele-ment <price> nach folgenden Kriterien:

• absteigende Reihenfolge, d.h. die teuersten Bücher zuerst (descen-ding);

• Bücher ohne Preisangabe werden an das Ende der Liste gesetzt (empty least).

• Sollten zwei Bücher gemäß diesen Regeln nicht unterscheidbar sein, so werden sie – unabhängig von der eingesetzten XQuery-Implementie-rung – gemäß ihrer Reihenfolge in den Inputdaten ausgegeben (stable).

Page 61: XQuery. Eine praxisorientierte Einführung  GERMAN

Sprachbestandteile

61

for $b in doc("input/bib.xml")/bib/book

stable order by $b/price descending empty least

return

<book>

{ $b/title }

{ $b/price }

</book>

2.2.4 Rückgabewert Jeder XQuery-Ausdruck muss neben der zwingenden Angabe mindestens einer For- und/oder Let-Klausel zur Einbindung von Inputdaten eine Return-Klausel enthalten, in der der XML-Rückgabewert des Ausdruckes erzeugt wird. Innerhalb dieses Rückgabewertes können alle bekannten Typen von XML-Knoten verwendet werden:

• Elementknoten • Attributknoten • Textknoten • Dokumentknoten • Verarbeitungsanweisungsknoten • Kommentarknoten • Namespace-Knoten

Zur Konstruktion dieser Knoten gibt es in XQuery jeweils zwei Möglichkei-ten:

• Direkte Konstruktion • Konstruktion durch Einsatz der jeweiligen Konstruktoren

In den bisherigen Beispielen dieses Buches wurde immer der erste Weg ge-wählt, also die direkte Konstruktion durch explizite Angabe der jeweiligen XML-Syntax in den Ausdrücken, beispielsweise bei einer Elementkonstruk-tion durch explizite Angabe von Tags in der folgenden Form:

Page 62: XQuery. Eine praxisorientierte Einführung  GERMAN

FLWOR-Ausdrücke

62

<book>

</book>

Bei der Nutzung von Konstruktoren muss in Abhängigkeit vom zu erzeugen-den Knotentyp die folgende Syntax verwendet werden:

• Elementknoten: element name { inhalt } • Attributknoten: attribute name { inhalt } • Dokumentknoten: document { inhalt } • Verarbeitungsanweisungsknoten: processing-instruction { in-

halt } • Kommentarknoten: comment { inhalt } • Namespace-Knoten: namespace name { inhalt } • Textknoten: siehe folgender Abschnitt über Textknoten.

Die folgenden beiden Beispiele erzeugen einen identischen Output, illustrie-ren aber die beiden Alternativen zur Erzeugung von Knoten (in diesem Bei-spiel von Element- und Attributknoten) in einer Return-Klausel. Zunächst die aus den bisherigen Beispielen bereits bekannte Variante über die direkte Konstruktion durch Angabe der jeweiligen XML-Syntax für Elemente und Attribute:

for $b in doc("input/bib.xml")/bib/book

where $b/@year = 2002

return

<buch autor= "{$b/author[1]/last}">

<titel> { string($b/title) } </titel>

<preis> { string($b/price) } </preis>

</buch>

Die alternative Variante nutzt den element-Konstruktor zur Konstruktion eines <buch>-Elementes. Dieses <buch>-Element wiederum setzt sich aus einem Attribut und zwei Unterelementen zusammen, die ebenfalls über ihre jeweiligen Konstruktoren attribute bzw. element angegeben sind.

Page 63: XQuery. Eine praxisorientierte Einführung  GERMAN

Sprachbestandteile

63

for $b in doc("input/bib.xml")/bib/book

where $b/@year = 2002

return

element buch

{ attribute autor { $b/author[1]/last },

element titel { xs:string($b/title) },

element preis { xs:string($b/price) } }

Beide Varianten liefern die folgende identische Ausgabe:

<buch autor="Holubek">

<titel>Tomcat 4x</titel>

<preis>24.90</preis>

</buch>

Ein Vorteil der zweiten Variante, also der Verwendung der knotentypspezifi-schen Konstruktoren, liegt darin, dass auch der Name eines Elementes bzw. eines Attributes dynamisch erzeugt werden kann, beispielsweise in der fol-genden Art:

element { compute_name(…) }

{ attribute autor { $b/author[1]/last },

}

wobei compute_name in diesem Beispiel eine benutzerdefinierte Funktion ist, in der der Algorithmus zur Berechnung des Elementnamens codiert ist. Eine Beschreibung von benutzerdefinierten Funktionen enthält Kapitel 2.5.4.

Textknoten

In den meisten der bisher in diesem Buch aufgelisteten Beispiele befanden sich in der Return-Klausel geschweifte Klammern { und }. Auch als Um-grenzung eines gesamten FLWOR-Ausdrucks kamen diese Klammern bereits vor, beispielsweise in diesem Ausdruck aus Kapitel 2.2.2:

Page 64: XQuery. Eine praxisorientierte Einführung  GERMAN

FLWOR-Ausdrücke

64

<andreas-buecher>

{

for $b in doc("input/bib.xml")//book

where some $a in $b/author

satisfies ($a/first="Andreas")

return

$b/title

}

</andreas-buecher>

Hier müssen zur Erzeugung des Inhaltes von <andreas-buecher> die Klammern um den gesamten XQuery-Ausdruck gesetzt werden. In der Re-turn-Klausel dieses Ausdruckes dagegen fehlen diese Klammern, da hier das <title>-Unterelement des über die Variable $b gebundenen <book>-Elementes unverändert übernommen wird, also mit Tags und Inhalt. Eine Verwendung der Klammern würde an dieser Stelle eine Fehlermeldung zur Folge haben.

(:

Fehlerhafte Abfrage

:)

<andreas-buecher>

{

for $b in doc("input/bib.xml")//book

where some $a in $b/author

satisfies ($a/first="Andreas")

return

{

$b/title

}

}

</andreas-buecher>

Wenn allerdings auch innerhalb der Return-Klausel explizite XML-Konstrukte aufgeführt sind, in die Werte von XQuery-Variablen integriert werden sollen, dann werden auch dort wieder die Klammern benötigt. Das

Page 65: XQuery. Eine praxisorientierte Einführung  GERMAN

Sprachbestandteile

65

folgende Beispiel zeigt zunächst einmal, was passiert, wenn in dieser Kon-stellation die Klammern nicht verwendet werden:

<andreas-buecher>

{

for $b in doc("input/bib.xml")//book

where some $a in $b/author

satisfies ($a/first="Andreas")

return

<Titel>

$b/title

</Titel>

}

</andreas-buecher>

Die in dieser Form sicherlich nicht beabsichtigte Ausgabe sieht nun wie folgt aus:

<andreas-buecher>

<Titel>

$b/title

</Titel>

<Titel>

$b/title

</Titel>

</andreas-buecher>

Was ist falsch gelaufen? Ohne die umschließenden Klammern wird die Zeile

$b/title

nicht als Auswertung der Variablen b mit dem angegebenen XPath-Ausdruck /child::title bzw. in Kurznotation /title interpretiert7, sondern unver-

7 also nicht als Erzeugung eines Textknotens auf der Basis eines über die Variable b und den XPath-Ausdruck selektierten Elementes in den Inputdaten

Page 66: XQuery. Eine praxisorientierte Einführung  GERMAN

FLWOR-Ausdrücke

66

ändert als Zeichenkette in die Ausgabe übernommen. Korrekt wäre in diesem Fall die folgende Variante

<andreas-buecher>

{

for $b in doc("input/bib.xml")//book

where some $a in $b/author

satisfies ($a/first="Andreas")

return

<titel>

{

$b/title

}

</titel>

}

</andreas-buecher>

mit dem Ergebnis

<andreas-buecher>

<titel>

<title>Java Persistenz Strategien</title>

</titel>

<titel>

<title>Tomcat 4x</title>

</titel>

</andreas-buecher>

Diese Ausgabe hat natürlich noch einen kleinen Schönheitsfehler. Da im XQuery-Ausdruck explizit der Element-Name <titel> aufgeführt ist, ist der aus den Inputdaten stammende Tagname <title> eigentlich überflüssig. Dieser Tagname kann beispielsweise wie folgt durch den Einsatz der string()-Funktion eliminiert werden.

Page 67: XQuery. Eine praxisorientierte Einführung  GERMAN

Sprachbestandteile

67

<andreas-buecher>

{

for $b in doc("input/bib.xml")//book

where some $a in $b/author

satisfies ($a/first="Andreas")

return

<titel>

{

string($b/title)

}

</titel>

}

</andreas-buecher>

Da durch den Einsatz der string()-Funktion nun nur der Textanteil des <title>-Elementes verwendet wird, sieht die Ausgabe dieses Ausdruckes nun wie folgt aus:

<andreas-buecher>

<titel>Java Persistenz Strategien</titel>

<titel>Tomcat 4x</titel>

</andreas-buecher>

An dieser Stelle sei auf die Kapitel 2.4 und 2.5 verwiesen, in denen das Typ-konzept sowie weitere Funktionen zur Umwandlung von Datentypen vorge-stellt werden.

Konkatenation

Der Rückgabewert eines XQuery-Audruckes kann auch aus mehreren einzel-nen Komponenten zusammengesetzt werden. Zu diesem Zweck wurde der Konkatenation-Operator in die Sprache aufgenommen, über den durch ein Komma getrennt zwei oder mehr Teile zu einem einzigen Rückgabewert zusammengefasst werden können.

Das folgende Beispiel zeigt den Einsatz dieses Operators. Hier soll eine Liste aller Buchtitel ausgegeben werden, die entweder mindestens zwei Autoren besitzen oder vor dem Jahr 2000 erschienen sind. Eine solche Abfrage könnte

Page 68: XQuery. Eine praxisorientierte Einführung  GERMAN

Operatoren

68

man natürlich durch eine passende ODER-Verknüpfung der beiden Bedin-gungen innerhalb der Where-Klausel formulieren. An dieser Stelle sei aber die folgende Alternative mit Einsatz des Konkatenations-Operators aufge-führt:

<buecherliste>

{

for $b in doc("input/bib.xml")/bib/book

let $a := $b/author

where count($a)>2

return

$b/title

,

for $b in doc("input/bib.xml")/bib/book

where xs:integer($b/@year) < 2000

return

$b/title

}

</buecherliste>

Das Ergebnis lautet:

<buecherliste>

<title>Java Persistenz Strategien</title>

<title>Tomcat 4x</title>

<title>Refactoring</title>

</buecherliste>

2.3 Operatoren In den folgenden Abschnitten werden nun die wichtigsten Operatoren vorge-stellt, die innerhalb von XQuery-Ausdrücken verwendet werden können.

Page 69: XQuery. Eine praxisorientierte Einführung  GERMAN

Sprachbestandteile

69

2.3.1 Logische Operatoren XQuery unterstützt die auch aus anderen Programmiersprachen bekannten logischen Operatoren and, or und not. Auch if-then-else-Konstrukte sind möglich.

And, Or, Not

Das folgende Beispiel enthält die drei logischen Operatoren and, or und not:

<buchliste>

{

for $b in doc("input/bib.xml")/bib/book

where $b/@year = 2002 and not(xs:decimal($b/price) >

30.00) or $b/publisher = "Addison-Wesley"

return

<buch>

{ $b/title }

</buch>

}

</buchliste>

Da auch in XQuery der and-Operator stärker bindet als der or-Operator, ergibt diese Abfrage folgendes Ergebnis:

<buchliste>

<buch>

<title>Tomcat 4x</title>

</buch>

<buch>

<title>Refactoring</title>

</buch>

</buchliste>

Durch geeignete Klammersetzung lässt sich natürlich auch in XQuery eine andere Auswertungsreihenfolge der logischen Operatoren erzwingen. Eine entsprechend durch Klammern ergänzte Where-Klausel

Page 70: XQuery. Eine praxisorientierte Einführung  GERMAN

Operatoren

70

where $b/@year = 2002

and (not(xs:decimal($b/price) > 30.00)

or $b/publisher = "Addison-Wesley")

verkürzt das Ergebnis daher auf

<buchliste>

<buch>

<title>Tomcat 4x</title>

</buch>

</buchliste>

If-then-else

Das nächste Beispiel illustriert den Einsatz einer if-then-else-Konstruktion in der Return-Klausel eines XQuery-Ausdruckes:

let $input := doc("input/bib.xml")

let $schnitt := avg($input//book/price)

return

<buchliste durchschnittspreis="{$schnitt}">

{

for $b in $input/bib/book

return

if( xs:decimal($b/price) < $schnitt)

then

<billiges_buch>

{ string($b/title) }

</billiges_buch>

else if ( xs:decimal($b/price) < 1.2*$schnitt )

then

<teueres_buch>

{ string($b/title) }

</teueres_buch>

else

Page 71: XQuery. Eine praxisorientierte Einführung  GERMAN

Sprachbestandteile

71

<sehr_teueres_buch>

{ string($b/title) }

</sehr_teueres_buch>

}

</buchliste>

Die avg-Funktion ist eine vordefinierte XQuery-Funktion zur Durchschnitts-bildung. In Kapitel 2.5.2 werden vordefinierte XQuery-Funktionen behan-delt. Das Ergebnis dieser Abfrage sieht wie folgt aus:

<buchliste durchschnittspreis="38.65">

<teueres_buch>Java Persistenz Strategien</teueres_buch>

<teueres_buch>Oracle, Java, XML</teueres_buch>

<billiges_buch>Tomcat 4x</billiges_buch>

<sehr_teueres_buch>Refactoring</sehr_teueres_buch>

</buchliste>

2.3.2 Arithmetische Operatoren Die folgenden bekannten arithmetischen Operatoren können in XQuery-Ausdrücken verwendet werden:

• +

• -

• * • div (Floating-Point-Division) • idiv (ganzzahlige Division) • mod (Modulo-Operation)

Zusätzlich existieren noch die folgenden vordefinierten XQuery-Funktionen:

• abs (Absoluter Wert) • avg (Durchschnittswert) • ceiling (Aufrundung auf den nächsthöheren ganzzahligen Wert) • floor (Abrundung auf den nächstniedrigeren ganzzahligen Wert) • min (Berechnung des Minimums) • max (Berechnung des Maximums)

Page 72: XQuery. Eine praxisorientierte Einführung  GERMAN

Operatoren

72

• round und round-half-to-even (Rundung zum nächsten Integer-Wert)8

• sum (Berechnung der Summe)

2.3.3 Vergleichs-Operatoren XQuery unterstützt die bekannten Vergleichsoperatoren

• = • != • < • <= • > • >=

Zu beachten ist aber ein wichtiger Unterschied zwischen Wertevergleichen und allgemeinen Vergleichen. Wertevergleiche erfordern mehr Typgenauig-keit als allgemeine Vergleiche. Während bei Wertevergleichen die Datenty-pen der beiden zu vergleichenden Objekte gleich sein müssen, können bei allgemeinen Vergleichen über die aufgeführten Operatoren auch Sequenzen mit atomaren Werten verglichen werden. Die folgenden beiden Abschnitte enthalten Beispiele, die diesen Unterschied verdeutlichen.

8 Der Unterschied zwischen den beiden Methoden besteht darin, auf welchen

Wert gerundet wird, falls zwei Werte gleich weit vom Ursprungswert entfernt

liegen: Die round-Funktion rundet in diesem Fall immer zum nächsthöheren

Wert, die round-half-to-even-Funktion zum nächstgelegenen geraden Wert.

Beispiel: round(2.5) = 3; round-half-to-even(2.5) = 2. Bei der round-half-to-

even-Funktion kann über einen optionalen Parameter zusätzlich noch die Stelle

angegeben werden, auf die die Rundungsoperation angewendet werden soll.

Page 73: XQuery. Eine praxisorientierte Einführung  GERMAN

Sprachbestandteile

73

Allgemeine Vergleiche

Das erste Beispiel zu einem allgemeinen Vergleich selektiert Bucheinträge anhand der Vor- und Nachnamen von Autoren.

for $b in doc("input/bib.xml")/bib/book

where $b/author/last = "Wolff"

and $b/author/first = "Andreas"

return

<book>

{ $b/title }

{ $b/author }

</book>

Das Ergebnis sieht wie folgt aus, ist allerdings vermutlich nicht das, was mit dieser Abfrage eigentlich erreicht werden sollte:

<book>

<title>Java Persistenz Strategien</title>

<author>

<last>Holubek</last>

<first>Andreas</first>

</author>

<author>

<last>Jansen</last>

<first>Rudolf</first>

</author>

<author>

<last>Munsky</last>

<first>Robert</first>

</author>

<author>

<last>Wolff</last>

<first>Eberhard</first>

</author>

</book>

Page 74: XQuery. Eine praxisorientierte Einführung  GERMAN

Operatoren

74

Wenn mit obiger Anfrage wirklich alle Bücher mit einem Autor “Andreas Wolff” gesucht werden sollten, dann ist dieses Ergebnis nicht das gewünsch-te. Die entscheidende Stelle in diesem Zusammenhang ist die where-Klausel

where $b/author/last = "Wolff"

and $b/author/first = "Andreas"

Die beiden XPath-Ausdrücke /author/last und /author/first werden zwar in jeder Iteration der for-Schleife für die identische Belegung der Vari-ablen b bearbeitet. Es ist aber nicht sichergestellt, dass in beiden XPath-Ausdrücken auch dasselbe <author>-Element bearbeitet wird. Wie man am Ergebnis der Abfrage erkennen kann, gibt es in den Inputdaten ein Buch mit einem Autor, der den Nachnamen „Wolff“ besitzt, und einen weiteren Autor mit Vornamen „Andreas“. Dieses Buch bzw. diese Belegung der Variablen b erfüllt also beide XPath-Bedingungen und wird daher über die Return-Klausel ausgegeben.

Um nun tatsächlich alle Bücher mit einem Autor „Andreas Wolff“ ermitteln zu können, muss also gewährleistet werden, dass sich die beiden XPath-Ausdrücke auf denselben Autor beziehen. Eine Möglichkeit dazu ist die fol-gende:

for $b in doc("input/bib.xml")/bib/book,

$a in $b/author

where $a/last = "Wolff"

and $a/first = "Andreas"

return

<book>

{ $b/title }

</book>

Hier werden zwei for-Schleifen geschachtelt aufgerufen. Eine andere Schreibweise der for-Klausel, die diese Verschachtelung besser verdeutlicht, ist die folgende:

for $b in doc("input/bib.xml")/bib/book

for $a in $b/author

...

Page 75: XQuery. Eine praxisorientierte Einführung  GERMAN

Sprachbestandteile

75

Für jedes Buch bzw. jedes <book>-Element wird nun explizit jeder Autor bzw. jedes <author>-Element durchlaufen. Somit ist sichergestellt, dass die folgenden beiden XPath-Ausdrücke auf demselben <author>-Element ope-rieren. Als Folge dieser Umstellung werden nun wirklich nur diejenigen Bücher angezeigt, die einen Autor mit Vornamen „Andreas“ und Nachnamen „Wolff“ besitzen. Da es einen solchen Eintrag in den Inputdaten nicht gibt, ist das Ergebnis dieses XQuery-Ausdrucks also leer.

Ein weiteres Beispiel, das die Auswertung von Vergleichsoperationen ver-deutlichen soll, ist das folgende:

<buchliste>

{

let $b:=doc("input/bib.xml")/bib/book

where $b/@year = 2002

return

<buch>

{ $b/title }

</buch>

}

</buchliste>

Der Variablen $b wird in diesem Beispiel einmalig eine Sequenz mit allen <book>-Elementen aus den Inputdaten zugewiesen. Für diese Gesamtse-quenz ist der Filterausdruck

where $b/@year = 2002

erfüllt, da es in der Sequenz ein Buch mit Erscheinungsjahr 2002 gibt. Somit wird in der Return-Klausel der XPath-Ausdruck

$b/title

für die gesamte Sequenz ausgewertet, was schließlich zu folgendem Ergebnis führt:

Page 76: XQuery. Eine praxisorientierte Einführung  GERMAN

Operatoren

76

<buchliste>

<buch>

<title>Java Persistenz Strategien</title>

<title>Oracle, Java, XML</title>

<title>Tomcat 4x</title>

<title>Refactoring</title>

</buch>

</buchliste>

Der entscheidende Punkt in diesem Vergleich ist also die Tatsache, dass im Filterausdruck

where $b/@year = 2002

eine Sequenz auf der linken Seite mit einem atomaren Wert auf der rechten Seite verglichen wird und dieser Vergleich bei Verwendung eines allgemei-nen Vergleichoperators genau dann erfüllt ist, wenn es in der Sequenz min-destens einen Wert gibt, der dem atomaren Wert auf der rechten Seite ent-spricht.

Die wahrscheinlich beabsichtigte Ausfilterung aller Bücher mit einem Er-scheinungsjahr ungleich 2002 könnte beispielsweise durch Austausch der Let-Klausel gegen eine For-Klausel wie folgt erreicht werden:

<buchliste>

{

for $b in doc("input/bib.xml")/bib/book

where $b/@year = 2002

return

<buch>

{ $b/title }

</buch>

}

</buchliste>

Page 77: XQuery. Eine praxisorientierte Einführung  GERMAN

Sprachbestandteile

77

Über allgemeine Vergleichsoperatoren können aber nicht nur Sequenzen mit atomaren Werten verglichen werden, sondern auch Sequenzen untereinander. In dieser Konstellation liefert der allgemeine Vergleichsoperator = den Wert true, falls es mindestens einen Wert in der linken Sequenz gibt, dessen Ver-gleich mit mindestens einem Wert aus der rechten Sequenz den Wert true ergibt. Oder anders formuliert: Zwei Sequenzen werden bei einem allgemei-nen Vergleich als gleich betrachtet, wenn ihre Schnittmenge nicht leer ist. Zur Illustration dient das folgende Beispiel:

let $books := doc("input/bib.xml")/bib/book

for $b in $books,

$c in $books

where $b/author = $c/author and $b/title != $c/title

return

<buchpaar>

{ $b/title }

{ $c/title }

</buchpaar>

Hier werden alle Bücher gesucht, die einen gemeinsamen Autor haben. Auf-grund der beschriebenen Regel zur Auswertung von allgemeinen Vergleichen zweier Sequenzen kann dies über den Vergleich

$b/author = $c/author

erfolgen, der den Wert true ergibt, falls die Autorenliste von $b mindestens einen Autor enthält, der auch in der Autorenliste von $c vorkommt. Wären nur diejenigen Bücher gesucht, bei denen alle Autoren gleich sind, so müsste der zugehörige Wertevergleichsoperator eq eingesetzt werden, der im fol-genden Abschnitt vorgestellt wird. Das Ergebnis der Abfrage mit dem allge-meinen Vergleichsoperator = lautet:

<buchpaar>

<title>Java Persistenz Strategien</title>

<title>Oracle, Java, XML</title>

</buchpaar>

<buchpaar>

Page 78: XQuery. Eine praxisorientierte Einführung  GERMAN

Operatoren

78

<title>Java Persistenz Strategien</title>

<title>Tomcat 4x</title>

</buchpaar>

<buchpaar>

<title>Oracle, Java, XML</title>

<title>Java Persistenz Strategien</title>

</buchpaar>

<buchpaar>

<title>Tomcat 4x</title>

<title>Java Persistenz Strategien</title>

</buchpaar>

Wertevergleiche

Da innerhalb von XQuery- bzw. XML-Anwendungen durchaus mehrere verschiedene Vergleichsverfahren benötigt werden, gibt es neben den im vorigen Abschnitt beschriebenen allgemeinen Vergleichen über die Operato-ren

• = • != • < • <= • > • >=

noch die folgenden sechs weiteren Operatoren, die Wertevergleiche durch-führen:

• eq (Test auf Gleichheit) • ne (Test auf Ungleichheit) • lt (Kleiner-Test) • le (Kleiner-oder-Gleich-Test) • gt (Größer-Test) • ge (Größer-oder-Gleich-Test)

Page 79: XQuery. Eine praxisorientierte Einführung  GERMAN

Sprachbestandteile

79

Diese Wertevergleichsoperatoren erfordern eine höhere Typgenauigkeit in zweierlei Hinsicht:

1. Ein Vergleich einer mehrelementigen Sequenz mit einem atomaren Wert ist nicht erlaubt und erzeugt daher eine entsprechende Fehlermeldung.

2. Die Datentypen der beiden zu vergleichenden Objekte müssen überein-stimmen.

Die folgenden beiden Beispiele zeigen jeweils einen fehlerhaften Einsatz des Wertevergleichs-Operators eq. Zunächst wird das zweite Beispiel aus dem vorigen Abschnitt umgestellt von einem allgemeinen Vergleich über den Operator = auf einen Wertevergleich mit dem Operator eq:

<buchliste>

{

let $b:=doc("input/bib.xml")/bib/book

where $b/@year eq 2002

return

<buch>

{ $b/title }

</buch>

}

</buchliste>

Der Wertevergleich

$b/@year eq 2002

verstößt gegen die erste oben aufgeführte Regel, da über den XPath-Ausdruck

$b/@year

eine Sequenz generiert wird, die bei einem Wertevergleich nicht mit dem atomaren Wert 2002 verglichen werden darf. Die genaue Fehlermeldung hängt von der eingesetzten XQuery-Implementierung ab. Die Implementie-rung IPSI (s. Kapitel 3.2.1) gibt folgende Fehlermeldung aus:

Page 80: XQuery. Eine praxisorientierte Einführung  GERMAN

Operatoren

80

Unexpected parameter type "2004 2003 2002 1999" for

function "http://www.w3.org/TR/xquery-semantics:eq"

expected was http://www.w3.org/2001/XMLSchema:NOTATION

Eine Korrektur dieses Fehlers ist möglich, indem aus der mehrelementigen Sequenz auf der linken Seite ein einzelner Wert extrahiert wird. In dem kor-rigierten Beispiel

<buchliste>

{

let $b:=doc("input/bib.xml")/bib/book

where $b[1]/@year eq 2002

return

<buch>

{ $b/title }

</buch>

}

</buchliste>

wird über den XPath-Ausdruck

$b[1]/@year

nur das Erscheinungsjahr des ersten <book>-Elementes in den eq-Vergleich einbezogen. Aber auch dieser Ausdruck ist noch fehlerhaft, da er gegen die zweite Wertevergleichs-Regel verstößt. In XQuery-Ausdrücken ohne zugrun-de liegende XML-Schema-Definition erfolgt für typlose Ausdrücke bei Wer-tevergleichen eine Typkonvertierung auf einen String-Wert. Im vorliegenden Beispiel ohne XML-Schema-Definition wird also das Attribut year als String behandelt. Demzufolge liegt in der Where-Klausel

where $b[1]/@year eq 2002

ein Wertevergleich zwischen einem String-Wert und einem numerischen Wert vor, also ein Verstoß gegen die zweite oben aufgeführte Regel bei Ein-satz von Wertevergleichen.

Page 81: XQuery. Eine praxisorientierte Einführung  GERMAN

Sprachbestandteile

81

Eine Korrektur dieses Fehlers durch eine explizite String-Angabe der Jahres-zahl 2002 ergibt nun einen fehlerfrei ausführbaren Ausdruck

<buchliste>

{

let $b:=doc("input/bib.xml")/bib/book

where $b[1]/@year eq "2002"

return

<buch>

{ $b[1]/title }

</buch>

}

</buchliste>

der allerdings ein leeres Element

<buchliste/>

als Ergebnis liefert, da das erste <book>-Element in der Inputdatei ein ande-res Erscheinungsjahr besitzt.

Im Gegensatz zu diesem Wertevergleich über den eq-Operator wäre ein allgemeiner Vergleich des Attributes year mit einem numerischen Wert über den =-Operator erlaubt gewesen:

where $b[1]/@year = 2002

Bei allgemeinen Vergleichen zwischen einem oder zwei Objekten ohne Typ-information wird dieser Vergleich nach den folgenden Regeln durchgeführt:

• Hat ein Objekt keinen Typ und das andere einen numerischen Datentyp, so wird das typlose Objekt als double-Wert interpretiert (diese Regel ist in obigem Beispiel angewendet worden).

• Haben beide keine zugrunde liegende Typinformation, so werden beide Objekte als string-Wert interpretiert.

• In allen anderen Fällen wird der dynamische Typ des einen Objektes bestimmt (s. Kapitel 2.4) und anschließend das typlose Objekt ebenfalls auf diesen Wert gecastet. Falls dies nicht möglich ist, wird eine entspre-chende Typumwandlungs-Fehlermeldung erzeugt.

Page 82: XQuery. Eine praxisorientierte Einführung  GERMAN

Operatoren

82

Boolean-Werte

Im Zusammenhang mit Vergleichsoperationen sind auch einige kurze An-merkungen zum Boolean-Datentyp erforderlich. Dabei sind nämlich der XML-Schema-Datentyp boolean, der über die entsprechende Namespace-Angabe xs:boolean9 gekennzeichnet ist, sowie der so genannte Effective Boolean Value (EBV) eines Ausdruckes zu unterscheiden, der über die XQuery-Funktion boolean() ermittelt werden kann. Diese Funktion boo-lean() verhält sich allerdings nicht immer identisch zu einem Typcast auf xs:boolean, wie die folgenden Beispiele zeigen:

let $a := ()

return

<boolean-test>

{

boolean(0),

boolean(1),

boolean(false()),

boolean(""),

boolean("false"),

xs:boolean("false"),

boolean($a)

}

</boolean-test>

Der über die boolean()-Funktion ermittelbare EBV eines Wertes ist false genau dann, wenn eine der folgenden Regeln erfüllt ist:

• Der Wert ist eine leere Sequenz. • Der Wert ist ein leerer String. • Es handelt sich um den xs:boolean-Wert false, der beispielsweise

über die Funktion false() generiert werden kann.

9 Über das xs-Präfix wird der XML-Schema-Namespace

http://www.w3.org/2001/XMLSchema gebunden.

Page 83: XQuery. Eine praxisorientierte Einführung  GERMAN

Sprachbestandteile

83

• Es handelt sich um den numerischen Wert 0. • Es handelt sich um den double- oder float-Wert NaN10.

Ist keine dieser Regeln erfüllt, so liefert die Funktion boolean() den Wert true. Gemäß diesen Regeln ergibt die obige Abfrage mit den boolean() und xs:boolean()-Aufrufen die folgende Ausgabe:

<boolean-test>

false

true

false

false

true

false

false

</boolean-test>

Dabei zeigen die beiden Aufrufe

boolean("false")

xs:boolean("false")

den wichtigen Unterschied zwischen diesen beiden Funktionen: Während bei der Bestimmung des EBV über die boolean()-Funktion der Inhalt des Strings nicht relevant ist (getestet wird bei String-Werten nur, ob diese leer sind oder nicht), ist für den Typcast mittels des xs:boolean-Aufrufes der Stringinhalt relevant. Der EBV des Strings „false“ ist also true, was bei Nichtbeachtung dieser Regel durch einen XQuery-Entwickler zu unerwarte-ten Effekten führen kann.

2.3.4 Reihenfolge-Operatoren Auch der Tatsache, dass die Reihenfolge von Knoten in XML-Input-dokumenten in Anwendungen und damit auch in Abfragen relevant sein 10 Der Wert NaN entspricht dem NULL-Wert für diese beiden Datentypen.

Page 84: XQuery. Eine praxisorientierte Einführung  GERMAN

Operatoren

84

kann, wurde beim Design von XQuery Rechnung getragen. Über die beiden Operatoren

• << • >> kann ein Vergleich der Platzierung zweier Knoten in der Dokumentenreihen-folge vorgenommen werden. Über die folgende Abfrage sollen alle Buchtitel ausgegeben werden, die im Inputdokument vor dem ersten Buch mit Erschei-nungsjahr 2002 aufgeführt sind.

<buchliste>

{

let $bib := doc("input/bib.xml")/bib

for $b in $bib/book

where $b << $bib//book[@year = 2002][1]

return

<buch>

{ $b/title }

</buch>

}

</buchliste>

Die entscheidende Zeile in dieser Abfrage ist die Where-Klausel

where $b << $bib//book[@year = 2002][1]

in der jedes Buch mit dem ersten im Inputdokument gefundenen Buch des Jahres 2002 (XPath-Ausdruck: $bib//book[@year = 2002][1]) vergli-chen wird. Zum Vergleich wird an dieser Stelle der Reihenfolge-Operator << eingesetzt. Das gesuchte Ergebnis lautet:

<buchliste>

<buch>

<title>Java Persistenz Strategien</title>

</buch>

Page 85: XQuery. Eine praxisorientierte Einführung  GERMAN

Sprachbestandteile

85

<buch>

<title>Oracle, Java, XML</title>

</buch>

</buchliste>

2.4 Typkonzept Wie zu Beginn dieses Buches bei der Beschreibung der Zielgruppe bereits erwähnt, soll das vorliegende Buch eine praxisorientierte Einleitung in die Sprache XQuery sein. Theoretische Grundlagen werden nur dort aufgeführt, wo sie zum Verständnis der Praxisbeispiele unbedingt notwendig sind. An dieser Stelle sei nochmals darauf hingewiesen, dass dies keine Abwertung dieser Theorie-Teile darstellen soll. Diese sind beim Entwurf einer neuen Sprache zwingend erforderlich, insbesondere für Entwickler von XQuery-Implementierungen. Das vorliegende Buch konzentriert sich aber in kompak-ter Form auf die Anwendung der Sprache. Bei der Vorstellung des Typkon-zeptes lässt sich die Behandlung von etwas Theorie zu Datentypen sowie dem zugrunde liegenden Datenmodell nicht ganz vermeiden.

Basis für viele in diesem Kapitel behandelte Themen ist der Begriff der Se-quenz. Wenn Sie dieses Buch von Anfang an durchgearbeitet haben, dann ist Ihnen dieser Begriff bereits an vielen Stellen begegnet. Ein XQuery-Ausdruck arbeitet immer auf einer Sequenz, also einer Folge von Werten. Eine solche Sequenz kann leer sein, es kann sich um eine mehrelementige Menge von Werten handeln, und auch einelementige Sequenzen sind mög-lich. Diese einelementigen Sequenzen sind äquivalent zu den entsprechenden atomaren Werten, d.h. die Sequenz (1) ist äquivalent zum numerischen Wert 1. Innerhalb eines XQuery-Ausdruckes kann überall dort, wo atomare Werte eingesetzt werden, auch die entsprechende einelementige Sequenz verwendet werden. Die Where-Klausel

where $b/@year = 2002

and xs:decimal($b/price) < 30.00

or $b/publisher = "Addison-Wesley"

Page 86: XQuery. Eine praxisorientierte Einführung  GERMAN

Typkonzept

86

aus dem Beispiel in Kapitel 2.3.1 ist also äquivalent zu der folgenden Ver-sion, in der anstelle der atomaren Werte jeweils einelementige Sequenzen verwendet werden:

where $b/@year = (2002)

and xs:decimal($b/price) < (30.00)

or $b/publisher = ("Addison-Wesley")

Jeder Datentyp eines XQuery-Ausdrucks wird durch zwei Bestandteile ge-kennzeichnet:

• Typname • Ein Indikator, der anzeigt, wie häufig der Typ vorkommen darf oder

muss (occurrence indicator)

Der Typname ist entweder einer der zahlreichen Basistypen (s. Kapitel 2.4.1) oder ein benutzerdefinierter Typ (s. Kapitel 2.4.2). Als Indikatorwert können die folgenden aus Regulären Ausdrücken bekannten Symbole eingesetzt werden:

• *: beliebige Anzahl • +: mindestens einer • ?: höchstens einer • Kein Indikator: genau einer

Einige Beispiele:

• xs:integer*: beliebige Anzahl von integer-Werten • mein_datentyp+: mindestens ein Wert, der den benutzerdefinierten

Datentyp mein_datentyp besitzt • node(): Genau ein Wert vom vordefinierten Typ node() (s. Kapitel

2.4.1)

In den folgenden Abschnitten werden nun die wichtigsten XQuery-Daten-typen vorgestellt. Dabei werden zunächst die vordefinierten Datentypen be-schrieben, bevor in Kapitel 2.4.2 dann die Möglichkeit zur Definition eigener Datentypen erläutert wird.

Page 87: XQuery. Eine praxisorientierte Einführung  GERMAN

Sprachbestandteile

87

2.4.1 Atomare Werte In Abbildung 1.7 des Einführungskapitels wurde bereits ein Überblick über die XML-Schema-Datentypen dargestellt. Diese bilden gleichzeitig die Grundlage für das XQuery-Typkonzept. Die „Herkunft“ eines bestimmten Datentyps lässt sich am verwendeten Namespace-Präfix erkennen: Ein Präfix xs: kennzeichnet den XML-Schema-Namespace http://www.w3.org/2001/ XMLSchema, während xdt: den entsprechenden XQuery-Typ-Namespace http://www.w3.org/2003/11/xpath-datatypes bezeichnet.

Numerische Typen

Die wichtigsten numerischen Datentypen sind

• xs:double

• xs:decimal

• xs:float

• xs:integer

Zum Datentyp xs:integer gibt es noch eine Reihe von abgeleiteten Daten-typen, die den jeweiligen XML-Schema-Datentypen entsprechen:

• xs:byte

• xs:int

• xs:long

• xs:short

• xs:negativeInteger

• xs:nonPositiveInteger

• xs:nonNegativeInteger

• xs:unsignedByte

• xs:unsignedInt

• xs:unsignedLong

• xs:unsignedShort

Wer XQuery-Abfragen portabel einsetzen will, d.h. mit unterschiedlichen XQuery-Implementierungen, sollte beim Einsatz dieser speziellen Integer-Typen vorsichtig sein. Der XQuery-Standard überlässt es den Herstellern dieser Implementierungen, mit welcher Genauigkeit sie solche numerischen

Page 88: XQuery. Eine praxisorientierte Einführung  GERMAN

Typkonzept

88

Werte verarbeiten. Ein Wechsel der Implementierung kann also Probleme verursachen, wenn diese Genauigkeit eine Rolle spielt.

Jeder der Datentypen besitzt entsprechende Konstruktoren, mit denen kon-krete Werte erzeugt werden können. Soweit möglich werden dabei Typum-wandlungen der angegebenen Parameter in das Zielformat vorgenommen. Falls dies nicht möglich ist, werden entsprechende Fehlermeldungen erzeugt. Die folgenden Ausdrücke zeigen vier erlaubte und einen fehlerhaften Kon-struktor-Aufruf:

xs:integer(1)

xs:integer(1.2)

xs:double(1)

xs:double("1.2")

xs:double("xyz")

Während die ersten vier Ausdrücke die folgenden Ergebnisse generieren:

1

1

1.0

1.2

erzeugt der letzte Ausdruck aufgrund der fehlgeschlagenen Typkonvertierung die folgende Fehlermeldung:

DynamicError: Unable to cast "xyz" as type

"http://www.w3.org/2001/XMLSchema:double".

Aber auch eine Konstruktion eines numerischen Wertes ohne einen expliziten Konstruktor-Aufruf ist möglich. Dabei gelten folgende Grundregeln:

• Numerische Werte ohne einen Dezimalpunkt werden als xs:integer-Wert interpretiert.

• Numerische Werte mit Dezimalpunkt, aber ohne die bekannte E-Nota-tion werden als xs:decimal interpretiert.

• Numerische Werte mit Dezimalpunkt und E-Notation werden als xs:double interpretiert.

Page 89: XQuery. Eine praxisorientierte Einführung  GERMAN

Sprachbestandteile

89

Die folgenden Ausdrücke entsprechen also in dieser Reihenfolge einem xs:integer-, einem xs:decimal- und einem xs:double-Wert:

4711

47.11

47.11E0

String-Typen

Der Datentyp xs:string wurde bereits in zahlreichen Beispielen dieses Buches eingesetzt. Daneben existieren noch die folgenden von xs:string abgeleiteten Datentypen, die allerdings nur selten verwendet werden:

• xs:normalizedString

• xs:token

• xs:language

• xs:Name

• xs:NMTOKEN

• xs:NMTOKENS

• xs:NCName

• xs:ID

• xs:IDREF

• xs:IDREFS

• xs:ENTITY

• xs:ENTITIES

Wie bereits bei den numerischen Datentypen beschrieben, können auch Strings durch einen expliziten xs:string()-Konstruktor oder durch einfa-che Wertzuweisung angelegt werden. Die folgenden Ausdrücke sind also äquivalent:

"test"

xs:string("test")

xs:string('test')

Eine Obergrenze für Stringlängen wird durch den XQuery-Standard nicht festgelegt und ist daher herstellerspezifisch.

Page 90: XQuery. Eine praxisorientierte Einführung  GERMAN

Typkonzept

90

Knoten-Typen

Als XML-Abfragesprache besitzt XQuery natürlich auch Datentypen, die die verschiedenen Knotentypen in XML-Dokumenten modellieren. Sie lauten:

• attribute()

• comment()

• document-node()

• element()

• namespace()

• processing-instruction()

• text()

Beispiele zur Konstruktion verschiedener Knotentypen enthält Kapitel 2.2.4. Ein Element-Knoten <buch> mit einem Attribut <autor> und zwei Unter-elementen <titel> und <preis> kann beispielsweise wie folgt angelegt werden:

element buch

{ attribute autor { $b/author[1]/last },

element titel { xs:string($b/title) },

element preis { xs:string($b/price) } }

Über die folgenden Funktionen kann auf spezielle Eigenschaften eines Kno-tens zugegriffen werden:

• base-uri()

• local-name()

• namespace-uri()

• node-kind()

• node-name() Außerdem gibt es noch die beiden Funktionen

• data()

• string()

über die auf den typed-value bzw. den string-value eines Knotens zugegriffen werden kann. Der typed-value eines Knotens mit einfachem

Page 91: XQuery. Eine praxisorientierte Einführung  GERMAN

Sprachbestandteile

91

Datentyp entspricht einer Sequenz von atomaren Werten mit den entspre-chenden Datentypen, während der string-value eine Aneinanderreihung der String-Darstellung aller Knotenbestandteile ist. Im folgenden Beispiel wird der string-value eines <book>-Elementes ermittelt.

for $b in doc("input/bib.xml")/bib/book

where $b/@year = 1999

return

string($b)

Da das selektierte <book>-Element in den Inputdaten die folgenden Unter-elemente enthält:

<book year="1999">

<title>Refactoring</title>

<author>

<last>Fowler</last>

<first>Martin</first>

</author>

<publisher>Addison-Wesley</publisher>

<price>49.90</price>

</book>

entspricht der string-value des <book>-Elementes also der Aneinander-reihung der String-Darstellung aller Unterelemente:

RefactoringFowlerMartinAddison-Wesley49.90

Zeit- und Datums-Typen

Neben einigen wohl eher selten zum Einsatz kommenden Datentypen zur Behandlung von Einträgen gemäß dem gregorianischen Kalender (xs:gDay, xs:gMonth, xs:gMonthDay, xs:gYear und xs:gYearMonth) stellt XQuery die folgenden Datentypen zum Umgang mit Zeit- und/oder Datums-angaben zur Verfügung:

• xs:date

• xs:dateTime

Page 92: XQuery. Eine praxisorientierte Einführung  GERMAN

Typkonzept

92

• xs:time

• xs:duration • xdt:dayTimeDuration11

• xdt:yearMonthDuration

Die ersten drei Typen kennzeichnen konkrete Zeitpunkte (mit Zeit- und/oder Datumsangabe), während die letzten drei Typen Zeitspannen darstellen. Die Syntax bei der Erstellung von Datumsangaben entspricht dem ISO 8601-Standard über die bereits aus anderen Programmiersprachen bekannten YYYY-MM-DDThh:mm:ss.sss…Z-Ausdrücke, bei dem die Buchstaben fol-gende Bedeutung haben:

• YYYY: Jahr • MM: Monat • DD: Tag • T: Konstante zur Trennung von Datums- und Zeitangaben • hh: Stunde • mm: Minute • ss.sss…: Sekunden • Z: Zeitzone (optional)

Da die bisher verwendeten Beispiele keine Datumsangaben enthielten, wird für das folgende Beispiel die nachfolgend wiedergegebene Inputdatei spiel-plan.xml mit einem Auszug aus dem Fußball-Bundesliga-Spielplan der Sai-son 2004/2005 verwendet:

<?xml version="1.0" encoding="ISO-8859-1"?>

<bundesliga>

<spieltag nr="2">

<datum>2004-08-14T15:30:00</datum>

<spiel>

11 Über die Aufnahme der beiden XQuery-spezifischen Datentypen xdt:day-TimeDuration und xdt:yearMonthDuration in den endgültigen Standard ist zum Zeitpunkt der Erstellung dieses Buchmanuskriptes noch keine Entscheidung gefallen.

Page 93: XQuery. Eine praxisorientierte Einführung  GERMAN

Sprachbestandteile

93

<heim>Bayern</heim>

<gast>Berlin</gast>

</spiel>

<spiel>

<heim>Schalke</heim>

<gast>Kaiserslautern</gast>

</spiel>

</spieltag>

<spieltag nr="3">

<datum>2004-08-28T15:30:00</datum>

<spiel>

<heim>Kaiserslautern</heim>

<gast>Stuttgart</gast>

</spiel>

<spiel>

<heim>Leverkusen</heim>

<gast>Bayern</gast>

</spiel>

</spieltag>

<spieltag nr="1">

<datum>2004-08-07T15:30:00</datum>

<spiel>

<heim>Bremen</heim>

<gast>Schalke</gast>

</spiel>

<spiel>

<heim>Hamburg</heim>

<gast>Bayern</gast>

</spiel>

</spieltag>

</bundesliga>

Es sollen nun alle Spiele an Spieltagen ausgegeben werden, die vor dem 20. August 2004 stattfinden. Folgender XQuery-Ausdruck kann dafür verwendet werden:

Page 94: XQuery. Eine praxisorientierte Einführung  GERMAN

Typkonzept

94

for $sp in doc("input/spielplan.xml")/bundesliga/spieltag

where xs:dateTime($sp/datum) < xs:dateTime("2004-08-

20T00:00:00")

order by xs:dateTime($sp/datum)

return

<spieltag nr="{ $sp/@nr }" anpfiff="{ get-hours-from-

dateTime($sp/datum),get-minutes-from-

dateTime($sp/datum) }">

<spiele>

{$sp//spiel}

</spiele>

</spieltag>

Dieser Ausdruck enthält Datums-Funktionen an mehreren Stellen. Zunächst werden ein aus den Inputdaten ausgelesener Wert sowie ein konstanter Wert in der Where-Klausel über den Konstruktor des xs:dateTime-Datentyps in das xs:dateTime-Format gebracht:

where xs:dateTime($sp/datum) < xs:dateTime("2004-08-

20T00:00:00")

Da in diesem Beispiel noch keine XML-Schema-Definition zugrunde gelegt wurde, ist der explizite Typcast des <datum>-Elementes auf den xs:date-Time-Datentyp erforderlich. Kapitel 2.4.2 beschreibt den Einsatz von XML-Schema-Definitionen in XQuery-Ausdrücken.

Wie aus den oben aufgelisteten Inputdaten ersichtlich ist, sind diese nicht chronologisch sortiert. Diese Aufgabe übernimmt daher im XQuery-Aus-druck eine entsprechende Order-By-Klausel:

order by xs:dateTime($sp/datum)

Bei der Konstruktion des Attributes anpfiff werden zwei der zahlreich vorhandenen Funktionen zur Behandlung von Datumswerten verwendet:

<spieltag nr="{ $sp/@nr }" anpfiff="{ get-hours-from-

dateTime($sp/datum),get-minutes-from-dateTime($sp/datum)

}">

Page 95: XQuery. Eine praxisorientierte Einführung  GERMAN

Sprachbestandteile

95

In diesem Fall wird über die Funktionen

• get-hours-from-dateTime()

• get-minutes-from-dateTime()

auf die Stunden- bzw. Minutenangabe im xs:dateTime-Objekt zugegriffen. Analoge Funktionen existieren für die weiteren Bestandteile von xs:date-Time sowie auch für die übrigen oben aufgeführten Datums- und Zeit-For-mate.

Das Ergebnis des XQuery-Ausdrucks lautet also:

<spieltag nr="1" anpfiff="15 30">

<spiele>

<spiel>

<heim>Bremen</heim>

<gast>Schalke</gast>

</spiel>

<spiel>

<heim>Hamburg</heim>

<gast>Bayern</gast>

</spiel>

</spiele>

</spieltag>

<spieltag nr="2" anpfiff="15 30">

<spiele>

<spiel>

<heim>Bayern</heim>

<gast>Berlin</gast>

</spiel>

<spiel>

<heim>Schalke</heim>

<gast>Kaiserslautern</gast>

</spiel>

</spiele>

</spieltag>

Page 96: XQuery. Eine praxisorientierte Einführung  GERMAN

Typkonzept

96

Sonstige Datentypen

Neben den in den vorigen Abschnitten vorgestellten numerischen, String- und Datums-Typen können noch weitere Datentypen in XQuery verwendet werden. Details zum xs:boolean-Datentyp inklusive der Besonderheiten beim Einsatz der boolean()-Funktion wurden bereits in Kapitel 2.3.3 be-handelt.

Zur Darstellung von XML-Namen dient der Datentyp xs:QName. Er besteht aus zwei Teilen: dem lokalen Namen und dem Namensraum des XML-Namens. Zum Anlegen eines solchen xs:QName existiert die Funktion ex-panded-QName,

expanded-QName("http://www.xyz.com/XML", "test")

die in diesem Beispiel den XML-Namen

http://www.xyz.com/XML:test

generiert.

In den bisherigen Beispielen lag keine Typinformation zu den einzelnen Werten vor. Trotzdem konnten die benötigten Operationen durchgeführt werden. In solchen Fällen wird der spezielle XQuery-Datentyp xdt:un-typedAtomic zugrunde gelegt. Er wird in der Regel wie ein xs:string verarbeitet.

2.4.2 Benutzerdefinierte Typen Wem die vorgestellten XQuery-spezifischen Datentypen nicht ausreichen, der kann eigene Datentypen definieren und in XQuery-Ausdrücken einsetzen. Definiert werden müssen diese Datentypen in XML-Schema-Definitionen. Zur Einbindung von XML-Schema-Definitionen steht das XQuery-Schlüssel-wort import zur Verfügung.

Ist beispielsweise ein eigener Adress-Datentyp AdressType in einer XML-Schema-Definition adress.xsd definiert,

Page 97: XQuery. Eine praxisorientierte Einführung  GERMAN

Sprachbestandteile

97

<schema targetNamespace=

"http://www.entwickler.com/buecher/xquery/adress"

xmlns="http://www.w3.org/2001/XMLSchema"

xmlns:adr="http://www.entwickler.com/buecher/xquery/

adress">

<complexType name="AdressType">

<sequence>

<element name="strasse" type="string"/>

<element name="nr" type="string"/>

<element name="plz" type="integer"/>

<element name="ort" type="string"/>

</sequence>

</complexType>

</schema>

so kann dieser wie folgt durch eine import-Anweisung in einen XQuery-Ausdruck importiert werden12:

import schema namespace adr =

"http://www.entwickler.com/buecher/xquery/adress" at

"input/adress.xsd";

Zum derzeitigen Zeitpunkt unterstützen noch nicht alle XQuery-Implemen-tierungen den Einsatz von XML-Schema (s. Kapitel 3). Wer eine Implemen-tierung mit XML-Schema-Unterstützung einsetzt, der kann den Datentyp AdressType nun in seinen XQuery-Ausdrücken einsetzen, z.B. als Datentyp von Funktionsparametern:

12 Die Angaben über den Speicherort der XML-Schema-Definition (in diesem Bei-spiel also die Angabe at "input/adress.xsd") können in Abhängigkeit von der eingesetzten XQuery-Implementierung variieren. Falls Sie ein solches Beispiel mit XML-Schema-Unterstützung testen wollen, überprüfen Sie bitte vorher die Anga-ben zu möglichen Default-Verzeichnissen, in denen Ihre XQuery-Implementierung die XML-Schema-Definitionen erwartet.

Page 98: XQuery. Eine praxisorientierte Einführung  GERMAN

Typkonzept

98

declare function checkAdress( $a as

element(adr:AdressType) )

Die in der XML-Schema-Definition definierten Datentypen werden gemäß obiger import-Klausel über den Namespace-Präfix adr gekennzeichnet. Eine andere Möglichkeit besteht darin, einen Default-Namespace anzugeben, auf den sich dann alle Präfix-freien Elemente beziehen. Dazu muss die im-port-Klausel wie folgt erweitert werden:

import schema default element namespace

"http://www.entwickler.com/buecher/xquery/adress" at

"input/adress.xsd";

2.4.3 Typoperatoren Dieser Abschnitt stellt einige der Operatoren vor, die den Umgang mit XQuery-Datentypen ermöglichen. Es handelt sich um Operatoren für Typ-umwandlungen sowie typabhängige Verarbeitung.

As

Durch den Zusatz

as type

kann der Datentyp von Variablen spezifiziert werden. Dies bietet den Vorteil, dass direkt bei der Wertebelegung überprüft werden kann, ob der angegebene Ausdruck den geforderten Typ hat. Wenn also über die folgende For-Klausel in einer Iteration der Variablen a ein Wert zugewiesen werden soll, der nicht den geforderten adressType-Datentyp hat, so wird eine entsprechende Feh-lermeldung erzeugt:

import schema namespace adr =

"http://www.entwickler.com/buecher/xquery/adress" at

"input/adress.xsd";

Page 99: XQuery. Eine praxisorientierte Einführung  GERMAN

Sprachbestandteile

99

for $a as element(adr:AdressType) in

doc("input/adress.xml")//address

return

bzw. nach Definition eines Default-Namespaces:

import schema default element namespace

"http://www.entwickler.com/buecher/xquery/adress" at

"input/adress.xsd";

for $a as element(AdressType) in

doc("input/adress.xml")//address

return

cast as, castable as, treat as

Auch aus anderen Programmiersprachen bekannt ist eine Casting-Operation, also die explizite Umwandlung eines Datentyps in einen anderen. XQuery besitzt zwei Operatoren für solche Typumwandlungen:

• cast as

• treat as

Eine vollständige Umwandlung von einem Typ in den anderen ist, wenn überhaupt, über den Operator cast as möglich. Der erste der folgenden beiden cast as-Ausdrücke liefert den integer-Wert 4711, während der zweite einen Fehler erzeugt, da der angegebene String nicht in einen inte-ger-Wert umgewandelt werden kann:

"4711" cast as xs:integer

"xyz" cast as xs:integer

Um solche Fehlermeldungen bei nicht durchführbaren Typumwandlungen zu vermeiden, kann vor dem cast as-Aufruf über einen castable as-Test überprüft werden, ob eine entsprechende Cast-Operation durchgeführt wer-

Page 100: XQuery. Eine praxisorientierte Einführung  GERMAN

Typkonzept

100

den kann. Der boolean-Rückgabewert einer castable as-Operation sig-nalisiert, ob der Ausdruck in den angegebenen Datentyp umgewandelt wer-den kann. Die Umwandlung selber wird durch castable as aber noch nicht vorgenommen:

if ($x castable as xs:integer)

then

$x cast as xs:integer

else

Eine in anderen Programmiersprachen als down-casting bezeichnete Um-wandlung von Datentypen innerhalb einer Typhierarchie ist über den Opera-tor treat as möglich. Im Gegensatz zur expliziten Typumwandlung zur Laufzeit beim Operator cast as wandelt treat as den Wert nicht explizit um, sondern behandelt ihn zur Compile-Zeit13 gemäß den Regeln des ange-gebenen Datentyps. Der Original-Datentyp und der hinter dem treat as-Operator angegebene Datentyp müssen voneinander abgeleitet sein. Während eine cast as-Umwandlung eines im String-Format vorliegenden numeri-schen Wertes in einen integer-Wert möglich ist

"4711" cast as xs:integer

würde die analoge treat as-Operation einen Fehler zur Compilezeit erzeu-gen, da der angegebene Datentyp integer nicht in einer Typhierarchie mit dem Datentyp string steht.

"4711" treat as xs:integer

instance of, typeswitch

Der Datentyp eines Ausdruckes kann über den instance of-Operator ge-testet werden. Der Test

13 Kapitel 3 beschreibt die Vorgehensweise beim Compilieren eines XQuery-Aus-druckes.

Page 101: XQuery. Eine praxisorientierte Einführung  GERMAN

Sprachbestandteile

101

"4711" instance of xs:integer

würde false ergeben, der Test

4711 instance of xs:integer

dagegen true. Typhierarchien werden beachtet, d.h. wird in einer XML-Schema-Definition ein Datentyp mystring als Erweiterung des vordefinier-ten Datentyps xs:string definiert, so ergibt der folgende Test ebenfalls den Wert true.

mystring("test") instance of xs:string

Soll in Abhängigkeit vom Datentyp eines Wertes eine bestimmte Aktion ausgeführt werden, so kann dies über geschachtelte if-then-else-Kon-strukte mit den jeweiligen instance of-Operatoren realisiert werden. Ein-facher und übersichtlicher ist aber in diesem Fall der Einsatz des type-switch-Operators. Er ist vergleichbar mit entsprechenden switch-case-Konstrukten in anderen Programmiersprachen und ermöglicht eine Differen-zierung in Abhängigkeit vom Datentyp eines Ausdruckes, nicht aber in Ab-hängigkeit vom konkreten Wert.

Eingesetzt wird ein typeswitch-Ausdruck häufig in Funktionen, die eine typabhängige Bearbeitung eines Parameterwertes vornehmen sollen. Im fol-genden Auszug eines XQuery-Ausdruckes wird in Abhängigkeit vom Daten-typ eine spezielle String-Ausgabe erzeugt.

typeswitch ( $b )

case $e as element()

return "Element"

case $a as attribute()

return "Attribut"

default

return "Anderer Typ"

Page 102: XQuery. Eine praxisorientierte Einführung  GERMAN

Typkonzept

102

2.4.4 Konvertierung Wie bereits in zahlreichen Beispielen dieses Buches gesehen, finden bei der Auswertung eines XQuery-Ausdruckes an vielen Stellen Typumwandlungen statt. Dies können explizit programmierte Cast-Operationen sein (s. voriger Abschnitt), es wurden allerdings auch schon einige Beispiele behandelt, in denen „hinter den Kulissen“ durch die XQuery-Implementierung Umwand-lungen vorgenommen werden müssen. Ein Beispiel dafür sind die in Kapitel 2.3.3 beschriebenen Regeln zur Ermittlung des Effective Boolean Value (EBV) eines Ausdruckes.

In Kapitel 2.2.3 wurde im Zusammenhang mit Sortiervorgängen das folgende Beispiel behandelt, in dem eine explizite Typumwandlung der ohne Typan-gabe vorliegenden <price>-Elemente in decimal-Werte vorgenommen werden musste:

order by xs:decimal($b/price)

Grund für diese explizite Typumwandlung war die Tatsache, dass ohne diese Angabe der <price>-Eintrag gemäß den string-Regeln verarbeitet werden würde, was im Rahmen der Sortierung zu dem Problem führt, dass eine lexi-kografische Sortierung vorgenommen wird, die nicht mit der eigentlich benö-tigten numerischen Sortierung übereinstimmen muss.

In diesem Zusammenhang ist auch der Begriff Atomization zu nennen. Er kennzeichnet die Umwandlung einer beliebigen Sequenz in die atomaren Werte ihrer einzelnen Bestandteile bzw. die Extraktion eines atomaren Wer-tes aus einem Knoten. Eine Atomization kann explizit durch den Aufruf der data()-Funktion vorgenommen werden. Häufiger kommt aber eine automa-tische Atomization vor, nämlich immer dann, wenn zur Ausführung einer Operation atomare Werte benötigt werden, im XQuery-Ausdruck aber Se-quenzen angegeben sind. Als Beispiel sei an dieser Stelle nochmals ein Aus-zug aus einem XQuery-Ausdruck aus Kapitel 2.3.1 aufgeführt, in dem über die avg()-Funktion der Durchschnittswert aller Preisangaben in einem In-putdokument berechnet wird:

let $schnitt := avg($input//book/price)

Page 103: XQuery. Eine praxisorientierte Einführung  GERMAN

Sprachbestandteile

103

Die avg()-Funktion arbeitet auf numerischen Werten. Über den als Parame-ter angegebenen XPath-Ausdruck wird aber die folgende Sequenz von <price>-Elementen selektiert:

<price>39.90</price>

<price>39.90</price>

<price>24.90</price>

<price>49.90</price>

Jeder der vier Einzelbestandteile dieser Sequenz muss also über eine implizi-te Atomization zunächst in das für die Anwendung der avg()-Funktion be-nötigte numerische Format gebracht werden.

2.5 Funktionen Häufig wiederkehrende Operationen werden in Programmiersprachen in der Regel nicht mehrfach implementiert, sondern in Form von Prozeduren und Funktionen zusammengefasst, die dann an den betreffenden Stellen mit den konkreten Parameterwerten aufgerufen werden. Auch XQuery bietet die Möglichkeit, Funktionen zu verwenden. Eine Reihe von Funktionen ist vor-definiert. Darüber hinaus besteht aber auch die Möglichkeit, selbst geschrie-bene Funktionen in XQuery-Ausdrücken zu nutzen.

2.5.1 Inputfunktionen Wer über die Stärken und Vorteile des Einsatzes von XML berichten soll, wird sehr schnell auf den Punkt Systemintegration kommen: XML als Daten-austauschformat für die Verbindung verschiedener Anwendungen auf unter-schiedlichen Plattformen und mit unterschiedlichen Programmiersprachen realisiert.

Als Abfragesprache für XML muss natürlich auch XQuery auf XML-Inputdaten aus unterschiedlichsten Quellen zurückgreifen können. Schwer-punkte sind dabei sicherlich der Dateizugriff auf XML-Dokumente sowie der Datenbankzugriff entweder direkt auf native XML-Datenbanken oder auf XML-Views in relationalen Systemen.

Page 104: XQuery. Eine praxisorientierte Einführung  GERMAN

Funktionen

104

In den bisherigen Beispielen wurde bei der Anbindung der Inputdaten immer der „Standardweg“ beschrieben, nämlich der Zugriff auf eine Datei über die doc()-Funktion:

for $b in doc("input/bib.xml")/bib/book

Die doc()-Funktion ist aber nicht die einzige Möglichkeit, Inputdaten in einen XQuery-Ausdruck einzubinden. Zusätzlich existiert noch die Funktion collection().

Der Rückgabewert der doc()-Funktion ist der so genannte Document Node eines XML-Dokumentes. Das Dokument selber wird im URI-Format ange-geben. Bei der Angabe von relativen Verzeichnisnamen wie im obigen Bei-spiel sollte immer die Dokumentation der verwendeten XQuery-Engine kon-sultiert werden, in der angegeben sein sollte, wie solche relativen Pfadanga-ben interpretiert werden.

Der Document Node als Rückgabewert der doc()-Funktion kann als eine Art Einstiegspunkt in ein XML-Dokument angesehen werden. Er ermöglicht daher die unmittelbare Angabe eines XPath-Ausdruckes, der beginnend an diesem Einstiegspunkt ansetzt:

doc("input/bib.xml")/bib/book

Etwas allgemeiner ausgelegt ist die andere Inputfunktion collection(). Über die collection()-Funktion, die ebenfalls einen Parameter in URI-Format benötigt, wird eine Sequenz von Knoten zurückgegeben. Wie diese Sequenz erzeugt wird, hängt von den vorgeschalteten Systemen ab, die die Sequenz an der angegebenen URI zur Verfügung stellen müssen. Eine Haupt-„Zielgruppe“ dieser Funktion sind die XML-Datenbanken. Verbirgt sich hinter der beim Aufruf der collection()-Funktion angegebenen URI also eine Datenbank, so kommen die Techniken ins Spiel, die der Hersteller dieser Datenbank zur XML- bzw. XQuery-Anbindung seines Produktes im Angebot hat.

Page 105: XQuery. Eine praxisorientierte Einführung  GERMAN

Sprachbestandteile

105

2.5.2 Vordefinierte Funktionen Bereits im if-then-else-Beispiel aus Kapitel 2.3.1 wurde mit der avg()-Funktion zur Durchschnittsbildung eine der vordefinierten XQuery-Funk-tionen genutzt. Diese Funktionen sind über den Namespace fn zusammenge-fasst, d.h. der Aufruf

let $schnitt := avg($input//book/price)

ist äquivalent zu

let $schnitt := fn:avg($input//book/price)

Jede Funktion wird definiert durch einen Namen, optionale Parameter sowie einen Rückgabewert. Insgesamt stehen in XQuery über 100 vordefinierte Funktionen zur Verfügung. Eine Vorstellung aller Funktionen würde den Rahmen dieses Buches sprengen. An dieser Stelle sei für eine Übersicht über alle Funktionen auf [XQF] verwiesen. Im Folgenden werden nun einige aus-gewählte Funktionen vorgestellt, um den grundsätzlichen Umgang mit vorde-finierten Funktionen zu illustrieren.

Sequenz-Funktionen

Über die count()-Funktion kann die Länge einer Sequenz ermittelt werden. Im folgenden Beispiel wird sie zur Bestimmung der Anzahl von <author>-Elementen verwendet.

for $b in doc("input/bib.xml")/bib/book

let $a := $b/author

return

<book>

{ $b/title }

<nr_authors> { count($a) } </nr_authors>

</book>

Alle <author>-Unterelemente des aktuellen <book>-Elementes werden zunächst über den Ausdruck

let $a := $b/author

Page 106: XQuery. Eine praxisorientierte Einführung  GERMAN

Funktionen

106

ermittelt. Die Auswertung der count()-Funktion für die so ermittelte Se-quenz in der Return-Klausel ergibt die gesuchte Anzahl, sodass das Ergebnis der gesamten Abfrage wie folgt aussieht:

<book>

<title>Java Persistenz Strategien</title>

<nr_authors>4</nr_authors>

</book>

<book>

<title>Oracle, Java, XML</title>

<nr_authors>1</nr_authors>

</book>

<book>

<title>Tomcat 4x</title>

<nr_authors>5</nr_authors>

</book>

<book>

<title>Refactoring</title>

<nr_authors>1</nr_authors>

</book>

Durch Einsatz der count()-Funktion innerhalb der Where-Klausel von XQuery-Ausdrücken lassen sich Abfragen durchführen, die im relationalen Bereich unter Einsatz von SQL einen höheren Aufwand bedeuten würden.

for $b in doc("input/bib.xml")/bib/book

let $a := $b/author

where count($a)>2

return

<book>

{ $b/title }

<nr_authors> { count($a) } </nr_authors>

</book>

In SQL müssten für solche Abfragen entweder Subselects eingebaut werden oder ein Zusatz der Art

Page 107: XQuery. Eine praxisorientierte Einführung  GERMAN

Sprachbestandteile

107

GROUP BY author HAVING COUNT(*) > 2

angehängt werden.

Weitere vordefinierte Funktionen zum Umgang mit Sequenzen lauten:

• distinct-values (s. weiter unten) • empty (Test, ob eine Sequenz leer ist) • exists (Test, ob eine Sequenz nicht leer ist) • index-of (Position eines Eintrages in der Sequenz) • insert-before (Eintrag eines oder mehrerer Werte in die Sequenz an

der festgelegten Stelle) • remove (Löschen eines oder mehrerer Werte in einer Sequenz) • reverse (Umkehren einer Sequenz durch Vertauschen der Reihenfolge

der enthaltenen Werte) • subsequence (Erzeugen einer Teilsequenz durch Angabe einer Startpo-

sition sowie einer optionalen Länge) • unordered (s. weiter unten)

Bereits zu Beginn von Kapitel 2.2 wurde die Funktion distinct-values zur Elimination von doppelten Einträgen einer Sequenz verwendet:

for $authorname in distinct-

values(doc("input/bib.xml")//author/last)

return …

Die Funktion unordered unterscheidet sich von den bislang vorgestellten Funktionen dadurch, dass sie keine Zusatzfunktionalität bietet, die direkt innerhalb der XQuery-Ausdrücke genutzt werden kann. Stattdessen kann man sie als eine Art Hinweis an die zugrunde liegende XQuery-Implemen-tierung verstehen, mit der man den dort enthaltenen Optimizer darüber unter-richtet, dass die Ordnung, in der die Inputdaten durchlaufen werden, für die Auswertung keine Rolle spielt. In der Regel wird ein Inputdokument in Do-kumentenreihenfolge durchlaufen. Dies muss aber nicht unbedingt die im Hinblick auf die Performance einer XQuery-Abfrage beste Reihenfolge sein.

Durch den Einsatz der unordered-Funktion in der folgenden Art

for $b in unordered(doc("input/bib.xml")//book)

Page 108: XQuery. Eine praxisorientierte Einführung  GERMAN

Funktionen

108

kann man den Optimizer der eingesetzten XQuery-Implementierung darüber unterrichten, dass er eine andere Reihenfolge der <book>-Elemente erzeugen und durchlaufen kann, falls er dies für sinnvoll hält. Ob und wie gut dieses Feature auch tatsächlich genutzt wird bzw. wie viel Performancegewinn dadurch zu erwarten ist, hängt natürlich entscheidend von der Struktur der Inputdaten sowie der Qualität des Optimizers in der verwendeten XQuery-Implementierung ab.

Gruppierung

Wenn Sie das vorliegende Buch bisher mit dem Ziel gelesen haben, Ähnlich-keiten und Unterschiede zwischen XQuery und SQL zu finden, dann werden Sie vor allem im Kapitel über die FLWOR-Ausdrücke eine Reihe von Ähn-lichkeiten entdeckt haben. Insbesondere die nicht nur aufgrund ihrer Be-zeichnungen vergleichbaren Where- und Order-By-Klauseln fallen in diesem Zusammenhang direkt auf. Eine SQL-Klausel fehlt allerdings: die GROUP BY-Klausel, über die in SQL-Abfragen eine Gruppierung des Ergebnisses gemäß einer Spalte erreicht werden kann. Im Standard-Beispiel dieses Bu-ches könnte man beispielsweise eine Abfrage suchen, mit der alle Autoren ausgegeben werden zusammen mit der Anzahl der Bücher, an denen sie mit-gearbeitet haben. In SQL könnte man dies recht bequem über den Zusatz

GROUP BY autor

erreichen. In XQuery fehlt diese Möglichkeit, was auch einer der Hauptkri-tikpunkte an der ersten Version von XQuery ist. Stattdessen muss man ent-sprechende Gruppierungen in XQuery selber vornehmen. Eine Möglichkeit zeigt das folgende Beispiel:

<autorenliste>

{

for $a in doc("input/bib.xml")//author

let $books :=

count(doc("input/bib.xml")//book[author=$a])

order by $books descending

return

Page 109: XQuery. Eine praxisorientierte Einführung  GERMAN

Sprachbestandteile

109

<autor>

{ $a/last }

<anzahl_buecher>

{ $books }

</anzahl_buecher>

</autor>

}

</autorenliste>

Hier werden zunächst in der For-Klausel alle Autoren selektiert. Zu jedem Autor werden dann in der folgenden Let-Klausel alle Bücher gesucht, bei denen der Autor in den <author>-Unterelementen vorkommt. Die Anzahl dieser Bücher wird dann in der Variablen $books gespeichert und dient in der Order-By-Klausel als Sortierkriterium.

Obwohl Gruppierungen also durch entsprechende selbstdefinierte Abläufe erreicht werden können, wäre eine Group-By-Klausel trotzdem wünschens-wert. Einerseits würde sie die Lesbarkeit von XQuery-Ausdrücken verbes-sern. Noch wichtiger wäre aber die Möglichkeit, XQuery-Implementierungen speziell für die Auswertung dieser Group-By-Klauseln weiterzuentwickeln. Im obigen Beispiel ist nämlich nicht gewährleistet, dass die XQuery-Imple-mentierung ihre Auswertestrategie auf die angestrebte Gruppierung ab-stimmt. Bei Verwendung einer Group-By-Klausel und zugehörigen Optimi-zer-Regeln für solche Klauseln in der Implementierung hätte man im Hin-blick auf die Performance der Abfrage eher die Hoffnung, dass eine zur Gruppierung passende Auswertungsreihenfolge gewählt wird.

2.5.3 Textfunktionen XQuery unterstützt die gängigen String-Operationen. Tabelle 2.1 enthält eine Aufstellung dieser Funktionen. In Vorgriff auf das letzte Kapitel dieses Bu-ches, das eine Beurteilung der ersten Version von XQuery inklusive einer Aufzählung der noch fehlenden Komponenten enthält, sei an dieser Stelle aber bereits darauf hingewiesen, dass Funktionen zur Volltextsuche in der ersten XQuery-Version noch fehlen.

Page 110: XQuery. Eine praxisorientierte Einführung  GERMAN

Funktionen

110

Funktion Parameter Rückga-bewert

Bedeutung

code-points-to-string

Sequenz von Inte-ger-Werten

String Umwandlung zwischen Unicode-Codepoint- und String-Darstellung

compare String, String

Integer Liefert -1, 0 oder 1 in Abhängigkeit davon, ob der erste String kleiner, gleich oder größer als der zweite String ist

concat String, String

String Konkatenation der beiden Input-strings

contains String, String

Boolean Liefert true, falls der erste ange-gebene String den zweiten enthält. Ansonsten false.

ends-with String, String

Boolean Liefert true, falls der erste ange-gebene String mit dem zweiten endet. Ansonsten false.

escape-uri

String, Boolean

String Umwandlung des ersten Parame-ters gemäß den Escape-Regeln des URI-Standards.

Der zweite Parameter gibt an, ob auch reservierte Zeichen (z.B. ; : @ & ) umgewandelt werden sollen

lower-case

String String Umwandlung aller Zeichen auf Kleinbuchstaben

matches String, String

Boolean Liefert true, falls der als erster Pa-rameter angegebene String dem als zweiten angegebenen regulären Ausdruck entspricht.

Page 111: XQuery. Eine praxisorientierte Einführung  GERMAN

Sprachbestandteile

111

Funktion Parameter Rückga-bewert

Bedeutung

replace String, String, String

String Der erste Parameter wird umge-wandelt. Dabei werden die über den zweiten Parameter als regulärer Ausdruck angegebenen Zeichen durch die über den dritten Parame-ter angegebenen Zeichen ersetzt.

starts-with

String, String

Boolean Liefert true, falls der erste ange-gebene String mit dem zweiten beginnt. Ansonsten false.

string-join

Sequenz von Strings, String

String Die Strings aus der als erster Para-meter angegebenen Sequenz wer-den aneinandergereiht. Dabei wer-den je zwei aufeinander folgende Strings durch den als zweiten Pa-rameter angegebenen String (z.B. ein Leerzeichen oder ein Semiko-lon) getrennt.

string-length

String Integer Ermittlung der Länge des Strings.

string-to-code-points

String Sequenz von Inte-ger-Werten

Umwandlung zwischen String- und Unicode-Codepoint-Darstellung

substring String, double, double

String Rückgabewert ist der Teilstring des ersten Parameters, der an der Posi-tion beginnt, die der zweite Parame-ter kennzeichnet. Ist der optionale dritte Parameter angegeben, so kennzeichnet dieser die Länge des Substrings.

Page 112: XQuery. Eine praxisorientierte Einführung  GERMAN

Funktionen

112

Funktion Parameter Rückga-bewert

Bedeutung

substring (Forts.)

String, double, double

String Fehlt der dritte Parameter, so reicht der Substring bis zum Ende des Originalstrings.

tokenize String, String

Sequenz von Strings

Aufsplitten des ersten Strings in eine Sequenz von Strings. An jeder Position, an der der als zweiter Parameter angegebene String im Originalstring auftritt, wird ein neuer String erzeugt.

translate String, String, String

String Umwandlung des ersten Parame-ters, indem alle Zeichen des zwei-ten Parameters durch die jeweiligen Zeichen des dritten Parameters ersetzt werden.

upper-case

String String Umwandlung aller Zeichen in Groß-buchstaben

Tabelle 2.1: Die wichtigsten XQuery-String-Funktionen

Im Zusammenhang mit String-Funktionen müssen auch die beiden Begriffe codepoints und collation erläutert werden. Über Codepoints werden in Unicode14 allen Zeichen eindeutige Integer-Werte zugewiesen. Jeder String lässt sich also auch als Sequenz von Unicode-Codepoints darstellen. Aus diesem Grund stellt XQuery zwei Funktionen

• codepoints-to-string

• string-to-codepoints zum Umrechnen zwischen einer String-Darstellung und der zugehörigen Sequenz von Unicode-Codepoints zur Verfügung.

14 Unicode ist die gängige Bezeichnung für den Universal Character Set (UCS), der wiederum die Grundlage für das W3C-Character-Model bildet.

Page 113: XQuery. Eine praxisorientierte Einführung  GERMAN

Sprachbestandteile

113

Über eine collation lassen sich Regeln zum Sortieren und zum Vergleich von String-Werten definieren. Eine collation kann bei den meisten String-Funktionen als optionaler Parameter angegeben werden. Alternativ kann im Prolog15 eines XQuery-Ausdruckes auch eine Default-collation ange-geben werden, die immer dann verwendet wird, wenn keine andere explizit angegebene collation verwendet werden soll. Angegeben wird eine col-lation immer im URI-Format. Vordefiniert und somit bei fehlenden Anga-ben in XQuery-Ausdrücken als Default-Wert verwendet ist die URI http:// www.w3.org/2003/11/xpath-functions/collation/codepoint.

2.5.4 Benutzerdefinierte Funktionen Während vordefinierte Funktionen unmittelbar in XQuery-Ausdrücken ver-wendet werden können, müssen selbst definierte Funktionen zunächst defi-niert werden. Dies erfolgt entweder unmittelbar vor dem Ausdruck, in dem die Funktion auch verwendet werden soll, oder in einem gesonderten Modul, in dem in der Regel mehrere Funktionen zusammengefasst werden und an-schließend über eine entsprechende import-Klausel in die XQuery-Aus-drücke importiert werden, in denen sie benötigt werden. Diese zweite Varian-te wird in Kapitel 2.6 behandelt. In den folgenden Beispielen werden gemäß der ersten Variante die Funktionen unmittelbar vor dem XQuery-Ausdruck definiert, in dem sie benutzt werden.

Meist werden Anweisungen, die an mehreren Stellen innerhalb eines Ausdru-ckes oder innerhalb einer Anwendung in nahezu unveränderter Form benutzt werden, in eine Funktion ausgelagert und an den Originalstellen durch einen entsprechenden Funktionsaufruf ersetzt. Als erstes Beispiel wird nun der folgende in Kapitel 2.3.4 bereits behandelte Ausdruck erweitert, in dem es um eine Reihenfolge-Auswertung von zwei Elementen ging:

15 siehe Kapitel 2.6

Page 114: XQuery. Eine praxisorientierte Einführung  GERMAN

Funktionen

114

<buchliste>

{

let $bib := doc("input/bib.xml")/bib

for $b in $bib/book

where $b << $bib//book[@year = 2002][1]

return

<buch>

{ $b/title }

</buch>

}

</buchliste>

Auch wenn der Reihenfolge-Operator << in diesem kleinen Beispiel nur an einer Stelle auftritt und auch nur aus einer einzelnen Operation besteht, so kann man sich trotzdem vorstellen, dass ein solcher Aufruf ein geeigneter Kandidat für eine Ausgliederung in eine separate Funktion ist, da es sich um Standardfunktionalität handelt, die häufig an mehreren Stellen verwendet wird.

Eine Ausgliederung in eine Funktion preceding kann wie folgt vorgenom-men werden.

declare function preceding ($x as element(), $y as

element())

as xs:boolean

{

$x << $y

};

let $bib := doc("input/bib.xml")/bib

for $b in $bib/book

where preceding($b, $bib//book[@year = 2002][1])

return

<buch>

{ $b/title }

</buch>

Page 115: XQuery. Eine praxisorientierte Einführung  GERMAN

Sprachbestandteile

115

Wie aus anderen Programmiersprachen bereits bekannt, enthält die Funkti-onsdefinition Typangaben zu den Parametern – im obigen Beispiel zwei element()-Parameter, zu denen im Gegensatz zu einem weiteren Beispiel weiter unten keine Angaben zu den Inhalten dieser Elemente vorgegeben sind – sowie zum Rückgabewert der Funktion. Insbesondere bei mehrfacher Ver-wendung dieser Funktion und nachträglicher Erweiterung der Funktionalität bietet eine Ausgliederung in eine Funktion den Vorteil, dass diese Ände-rung16 nur einmalig vorgenommen werden muss.

Anhand des nächsten Beispieles soll nun ein weiterer Vorteil des Einsatzes von Funktionen illustriert werden. Es handelt sich um eine Verbesserung der Typsicherheit von Ausdrücken. Wird eine Funktion mit Parametern aufgeru-fen, die nicht den Typangaben in der Funktionsdefinition entsprechen, so wird eine entsprechende Fehlermeldung generiert. Als Ausgangsbasis für dieses Beispiel dient die folgende Funktion getAuthorname:

declare function getAuthorname ($a as element())

as string

{

let $name := string($a/last)

return $name

};

for $a in doc("input/bib.xml")//author

return

getAuthorname( $a )

In diesem Beispiel besteht der in der Funktion getAuthorname erzeugte Name ausschließlich aus dem Stringwert des im Parameter-Element enthalte-nen <last>-Eintrages, sodass folgendes Ergebnis ausgegeben wird:

16 Mögliche Erweiterungen der Funktion preceding() wären beispielsweise eine Verallgemeinerung auf Vergleiche beliebiger Knoten (nicht nur Elementknoten) sowie eine Vorschrift zur Behandlung von Elementen bzw. Knoten, bei denen einer der beiden Parameter den anderen enthält.

Page 116: XQuery. Eine praxisorientierte Einführung  GERMAN

Funktionen

116

Holubek

Jansen

Munsky

Wolff

Jansen

Holubek

Poeschmann

Roewekamp

Rossbach

Tabatt

Fowler

Die Tatsache, dass bei der Parameterübergabe der Funktion eine Typüberprü-fung stattfindet, bemerkt man spätestens dann, wenn man versucht, die dop-pelten Einträge in dieser Liste durch den Einsatz der distinct-values-Funktion in der folgenden Art zu eliminieren:

declare function getAuthorname ($a as element())

as string

{

let $name := string($a/last)

return $name

};

for $a in distinct-values(doc("input/bib.xml")//author)

return

getAuthorname( $a )

Bei der Ausführung dieser Abfrage tritt folgende Fehlermeldung auf:

Unexpected parameter type for function "getAuthorname"

expected was "xs:AnyElement".

Was ist passiert? Der Rückgabewert der Funktion distinct-values() hat den Typ xdt:anyAtomicType*. Die Funktion getAuthorname erwartet aber einen Parameter in element()-Format.

Page 117: XQuery. Eine praxisorientierte Einführung  GERMAN

Sprachbestandteile

117

Während in diesem Beispiel nur eine Überprüfung dahingehend erfolgt, dass ein element()-Parameter übergeben wird, ist es zusätzlich auch noch mög-lich – und in vielen Konstellationen, in denen Typsicherheit erforderlich ist, auch sehr sinnvoll –, den Datentyp der übergebenen Elemente in der Parame-terliste aufzuführen. Wird das obige Beispiel also wie folgt durch eine im-port-Klausel zum Importieren einer XML-Schema-Definition sowie eine Zusatzangabe beim Parametertyp der getAuthorname()-Funktion erwei-tert,

import schema namespace bib =

"http://www.entwickler.com/buecher/xquery/bib" at

"input/bib.xsd";

declare function getAuthorname ($a as

element(bib:AuthorType))

as string

{

let $name := string($a/last)

return $name

};

for $a in distinct-values(doc("input/bib.xml")//author)

return

getAuthorname( $a )

dann liefert ein Aufruf der Funktion mit einem Parameter, der zwar als Ele-ment vorliegt, aber dessen Inhalt nicht den in der XML-Schema-Definition geforderten Datentyp AuthorType aus dem Namensraum bib besitzt, eben-falls eine Fehlermeldung. Existiert beispielsweise in der Inputdatei bib.xml keine Angabe zu einer zugrunde liegenden XML-Schema-Definition, so liefert die Typüberprüfung beim Aufruf von getAuthorname ein negatives Ergebnis, das mit einer entsprechenden Fehlermeldung endet:

Page 118: XQuery. Eine praxisorientierte Einführung  GERMAN

Funktionen

118

Unexpected parameter type for function "getAuthorname"

expected was "element http://www.entwickler.com/buecher/

xquery/bib:AuthorType ".

Rekursive Funktionen

Bei XQuery-Funktionen kann es sich auch um rekursive Funktionen handeln, also um Funktionen, die sich selber aufrufen. Die Rekursivität kann dabei entweder durch eine rekursive Berechnung des Funktionswertes verursacht oder durch die rekursive Struktur der zu verarbeitenden XML-Konstrukte erforderlich sein.

Als Beispiel für eine rekursive Funktion diene die folgende Implementierung einer Exponentialfunktion. Wie der Aufstellung der vordefinierten arithmeti-schen Funktionen in Kapitel 2.3.2 zu entnehmen ist, stellt XQuery eine sol-che Funktion nicht zur Verfügung. Sie kann aber wie folgt selber realisiert werden:

declare function exp ($b as xs:integer,

$e as xs:integer)

as xs:integer

{

if ($e < 1 )

then

1

else

$b * exp( $b, $e - 1 )

};

let $x:=exp(2, 6)

return $x

Als Ergebnis dieses Ausdruckes inklusive des Aufrufs der selbst geschriebe-nen exp-Funktion wird erwartungsgemäß die Zahl 64 ausgegeben.

Weitere Anwendungsgebiete für rekursive Funktion sind Verarbeitungen von (XML-)Baumstrukturen, bei denen eine Funktion für jeden Knoten oder für jede Ebene innerhalb der Hierarchie gesondert aufgerufen werden soll.

Page 119: XQuery. Eine praxisorientierte Einführung  GERMAN

Sprachbestandteile

119

2.5.5 Externe Funktionen Eine innerhalb eines XQuery-Ausdruckes verwendete Funktion kann auch extern realisiert sein. Es ist also möglich, eine Funktion beispielsweise in Java zu realisieren und dann in XQuery zu benutzen. Die Tatsache, dass eine Funktion extern realisiert ist, muss durch den Zusatz external in der fol-genden Art erfolgen:

define function myExternalFunction($p as xs:integer)

as xs:integer external

Auch Variablen können extern definiert sein:

define variable $myExternalVariable as xs:integer

external

Die genaue Syntax zur Einbindung von externen Variablen ist abhängig von der eingesetzten XQuery-Implementierung.

2.6 Module und Prolog Die bisher in diesem Buch behandelten Beispiele bestanden immer nur aus einer einzigen Abfrage. In der Praxis wird man aber eher auf Situationen treffen, in denen in einer Anwendung oder einem Projekt mehrere Abfragen verwendet werden.

Wie bereits in Kapitel 2.5.4 beschrieben wurde, besteht die Möglichkeit, eine Folge von Verarbeitungsschritten in benutzerdefinierten Funktionen zusam-menzufassen. Solche Funktionen können dann in Abfragen genutzt werden, die unmittelbar auf die Funktionsdefinition folgen (s. Beispiele in Kapitel 2.5.4). Viel häufiger dürfte aber die Situation auftreten, dass eine Funktion in mehreren Abfragen eines Projektes genutzt werden soll. Für diesen Fall kann eine Funktion in einem gesonderten Modul definiert werden, das dann von allen Abfragen, die die Funktion einsetzen wollen, importiert werden kann.

Zur Veranschaulichung soll nun das folgende Beispiel aus Kapitel 2.5.4 um-geschrieben werden:

Page 120: XQuery. Eine praxisorientierte Einführung  GERMAN

Module und Prolog

120

declare function preceding ($x as element(), $y as

element())

as xs:boolean

{

$x << $y

};

let $bib := doc("input/bib.xml")/bib

for $b in $bib/book

where preceding($b, $bib//book[@year = 2002][1])

return

<buch>

{ $b/title }

</buch>

Damit die Funktion preceding auch in anderen Abfragen genutzt werden kann, wird sie in ein eigenes Modul bzw. eine eigene Datei ausgegliedert. Ein XQuery-Modul kann das so genannte main module sein. In den bisherigen Beispielen mit nur einer einzigen Abfrage handelte es sich immer um dieses main module. Zusätzlich können aber noch library modules eingesetzt werden, in die – vergleichbar mit dem Bibliothekskonzept anderer Program-miersprachen – Bestandteile von XQuery-Ausdrücken ausgegliedert werden. Im Gegensatz zum main module enthält ein library module keine direk-ten Abfragen, sondern nur benutzerdefinierte Funktionen sowie globale Vari-ablen. Ein library module für die Funktion preceding kann wie folgt aussehen:

module namespace my_functions = "urn:my-function-

definitions";

declare function my_functions:preceding ($x as element(),

$y as element())

as xs:boolean

{

$x << $y

};

Page 121: XQuery. Eine praxisorientierte Einführung  GERMAN

Sprachbestandteile

121

In der ersten Zeile wird nach dem Schlüsselwort module der Namensraum für dieses Modul festgelegt. Über diesen Namensraum werden die in diesem Modul definierten Funktionen und Variablen später identifiziert. So ist es beispielsweise auch möglich, mehrere Funktionen mit identischem Namen in verschiedenen Modulen und verschiedenen Namensräumen zu definieren und innerhalb von Abfragen dann anhand ihres Namensraumes zu identifizieren.

Bezeichnungen für Namensräume können frei vergeben werden, solange die Eindeutigkeit gewährleistet ist. Häufig findet man Namensraumbezeichnun-gen nach einem URL-Muster. Für vordefinierte Datentypen und Funktionen existieren bereist einige vordefinierte Namensräume, z.B.

• fn = http://www.w3.org/2003/11/xpath-functions für vor-definierte Funktionen

• xdt = http://www.w3.org/2003/11/xpath-datatypes für die XQuery-eigenen Datentypen

• xs = http://www.w3.org/2001/XMLSchema für die in XML-Schema definierten Datentypen

Innerhalb des main modules, also in der Datei, die den auszuführenden XQuery-Ausdruck enthält, kann ein library module durch eine entspre-chende import-Klausel wie folgt eingebunden werden:

import module namespace my_functions = "urn:my-function-

definitions" at "modules/preceding_module.xquery";

let $bib := doc("input/bib.xml")/bib

for $b in $bib/book

where my_functions:preceding($b, $bib//book[@year =

2002][1])

return

<buch>

{ $b/title }

</buch>

Die Angabe zur Lokalisierung einer Datei, in der ein library module gefun-den werden kann, ist implementierungsspezifisch. Im vorliegenden Beispiel erfolgte diese Angabe durch Spezifikation eines relativen Dateinamens über

Page 122: XQuery. Eine praxisorientierte Einführung  GERMAN

Joins

122

eine at-Klausel am Ende der import-Klausel. Wenn Sie dieses oder ähnli-che Beispiele mit selbst geschriebenen Modulen austesten wollen, sollten Sie zunächst einen Blick in die Dokumentation der von Ihnen benutzten XQuery-Implementierung werfen, da es in Ihrer Implementierung andere Wege zur Lokalisierung solcher Dateien geben kann.

import module namespace my_functions = "urn:my-function-

definitions" at "modules/preceding_module.xquery";

Eine solche import-Klausel ist Bestandteil des Modul-Prologes. Weitere (optionale) Bestandteile des Prologs können u.a. die folgenden Konstrukte sein:

• Namensraum-Definitionen

declare namespace buch =

http://www.entwickler.com/buecher/xquery;

• Variablendeklarationen

declare variable $counter as xs:integer ( 0 );

• Import von XML-Schema-Definitionen zur Erweiterung der Menge der verwendeten Datentypen, s. dazu auch Kapitel 2.4.2

import schema namespace adr =

"http://www.entwickler.com/buecher/xquery/adress" at

"input/adress.xsd";

2.7 Joins SQL-Abfragen in relationalen Datenbanken beschränken sich meist nur in einfachen Beispielen auf eine einzige Tabelle. Stattdessen findet man in der Regel Join-Abfragen über mehrere Tabellen, bei denen die gesuchten Tabel-leninhalte durch Vergleich der Join-Spalten wie folgt ermittelt werden:

SELECT t1.x, t1.y, t2.a

FROM tabelle1 t1, tabelle2 t2

WHERE t1.x=t2.b

Page 123: XQuery. Eine praxisorientierte Einführung  GERMAN

Sprachbestandteile

123

Dieses Szenario wurde natürlich auch beim Entwurf von XQuery berücksich-tigt. Auch bei der Verarbeitung von XML-Daten liegen diese in der Regel nicht nur in einer einzelnen Datei bzw. einer einzigen Datenquelle vor, son-dern müssen aus mehreren Quellen zusammengefügt werden.

Das Vorgehen zur Integration von Daten aus mehr als einem Inputdokument zeigt das folgende Beispiel, in dem Daten aus zwei Inputdateien bib.xml und adress.xml verarbeitet werden.

<Autoren>

{

let $buch := doc("input/bib.xml")//book

let $addresse := doc("input/adress.xml")//address

for $b in $buch,

$a in $addresse

where $b/title = "Java Persistenz Strategien"

and $b/author/last = $a/last

return

<Autor Name="{ $a/last }" Ort="{ $a/city }"/>

}

</Autoren>

Analog zur Definition einer Join-Bedingung in SQL werden auch in diesem XQuery-Ausdruck die Elemente, über die die Verbindung zwischen den beiden Inputdatenquellen erfolgen soll, innerhalb der Where-Klausel angege-ben:

$b/author/last = $a/last

Mit den in Kapitel 2.1 angegebenen Inputdateien lautet das Ergebnis dieser Abfrage:

<Autoren>

<Autor Name="Holubek" Ort="Dresden"/>

<Autor Name="Jansen" Ort="Aachen"/>

<Autor Name="Munsky" Ort="Dresden"/>

<Autor Name="Wolff" Ort="Hamburg"/>

</Autoren>

Page 124: XQuery. Eine praxisorientierte Einführung  GERMAN

Joins

124

Nachteil dieser Formulierung der XQuery-Anfrage ist die Tatsache, dass nur dann eine Ausgabe erfolgt, wenn es zu dem betreffenden Buch mindestens einen Autor gibt, der auch einen Eintrag in der Adressdatei adress.xml be-sitzt. Möchte man aber eine XQuery-Abfrage zu der Fragestellung „Gib zu jedem Buch aus der Bücherliste den Titel sowie den Namen und den Ort aller Autoren, die in der Adressdatei eingetragen sind“ formulieren, so muss dies wie folgt gemacht werden:

let $buch := doc("input/bib.xml")//book

let $addresse := doc("input/adress.xml")//address

for $b in $buch

return

<Buch>

{ $b/title }

{

for $a in $addresse

where $b/author/last = $a/last

return

<Autor Name="{ $a/last }" Ort="{ $a/city }"/>

}

</Buch>

Das gesuchte Ergebnis lautet nun

<Buch>

<title>Java Persistenz Strategien</title>

<Autor Name="Holubek" Ort="Dresden"/>

<Autor Name="Jansen" Ort="Aachen"/>

<Autor Name="Munsky" Ort="Dresden"/>

<Autor Name="Wolff" Ort="Hamburg"/>

</Buch>

<Buch>

<title>Oracle, Java, XML</title>

<Autor Name="Jansen" Ort="Aachen"/>

</Buch>

Page 125: XQuery. Eine praxisorientierte Einführung  GERMAN

Sprachbestandteile

125

<Buch>

<title>Tomcat 4x</title>

<Autor Name="Holubek" Ort="Dresden"/>

</Buch>

<Buch>

<title>Refactoring</title>

</Buch>

und enthält auch zum „Refactoring“-Buch einen Eintrag, obwohl dessen einziger Autor nicht in der Adressdatei eingetragen ist (left outer join).

2.8 Fehlerbehandlung In jedem Lehrbuch über eine neue Programmiersprache finden sich Hinweise zur Behandlung von Programmfehlern. Wie geht XQuery also mit Fehlern um? Zunächst müssen bei dieser Frage statische und dynamische Fehler un-terschieden werden. Statische Fehler können bereits zur Compilezeit aus-schließlich anhand der XQuery-Abfrage und ohne Vorlage von Inputdaten erkannt werden, während dynamische Fehler erst zur Laufzeit auftreten und daher auch erst zu diesem Zeitpunkt behandelt werden können. Eine genaue-re Unterscheidung zwischen statischen und dynamischen Fehlern sowie den Verarbeitungsschritten, in denen diese erkannt werden, folgt in Kapitel 3.1 unmittelbar vor der Vorstellung bereits verfügbarer XQuery-Implementierun-gen.

Außerdem ist zu unterscheiden zwischen Fehlern, die aus fehlerhaftem Ein-satz von XQuery-Sprachbestandteilen resultieren, sowie benutzerdefinierten Fehlermeldungen. Als Beispiel für die erste Gruppe von Fehlern sei an dieser Stelle nochmals das in Kapitel 2.3.3 bereits aufgeführte Beispiel mit einem fehlerhaften Vergleich aufgeführt,

<buchliste>

{

let $b:=doc("input/bib.xml")/bib/book

where $b/@year eq 2002

return

Page 126: XQuery. Eine praxisorientierte Einführung  GERMAN

Fehlerbehandlung

126

<buch>

{ $b/title }

</buch>

}

</buchliste>

bei dem im Wertevergleich

$b/@year eq 2002

eine Sequenz mit einem atomaren Wert verglichen wird, was zu der folgen-den Fehlermeldung führt:

Unexpected parameter type "2004 2003 2002 1999" for

function "http://www.w3.org/TR/xquery-semantics:eq"

expected was http://www.w3.org/2001/XMLSchema:NOTATION

Neben solchen Systemfehlermeldungen können auch benutzerdefinierte Feh-lermeldungen ausgegeben werden. Dazu steht die Funktion error() zur Verfügung, die analog zu den Systemfehlermeldungen zu einem Abbruch der Abfrageverarbeitung führt. Im folgenden Beispiel wird die Funktion er-ror() eingesetzt, um die Verarbeitung von bestimmten Inputdaten zu ver-hindern:

let $input := doc("input/bib.xml")

return

<buchliste>

{

for $b in $input/bib/book

return

if( $b/publisher = "<Verlag A>" )

then

else if( $b/publisher = "<Verlag B>" )

then

Page 127: XQuery. Eine praxisorientierte Einführung  GERMAN

Sprachbestandteile

127

else

error()

}

</buchliste>

Wird bei der Verarbeitung der Inputdatei ein <book>-Element gefunden, dessen publisher-Angabe nicht einer der in der if-then-else-Klausel angegebenen Werte entspricht, so wird anstelle einer Ausgabe der Ergebnis-werte eine Fehlermeldung der folgenden Art ausgegeben:

XQueryException (13, 7): Error function was called.

Probably dynamic type error.

Das genaue Format einer solchen Fehlermeldung hängt von der eingesetzten Implementierung ab. Ebenfalls implementierungsabhängig sind die Möglich-keiten, über einen optionalen Parameter der error()-Funktion weitere In-formationen zum aufgetretenen Fehler auszugeben, beispielsweise durch eine benutzerdefinierte Fehlermeldung,

error("Unbekannter Verlag")

die dann – in Abhängigkeit von der eingesetzten Implementierung – wie folgt ausgegeben wird:

XQueryException: Unbekannter Verlag

Nochmals hervorgehoben sei die Tatsache, dass bei Auftreten eines Fehlers die komplette Verarbeitung des XQuery-Ausdruckes verhindert wird. Es gibt derzeit noch keine Möglichkeit, auf Fehler zu reagieren. Im Gegensatz bei-spielsweise zu Java-Anwendungen, in denen über try-catch-Blöcke der folgenden Art

Page 128: XQuery. Eine praxisorientierte Einführung  GERMAN

Fehlerbehandlung

128

try {

// …

} catch( Exception e ) {

}

Fehler in Unterausdrücken abgefangen und bei Bedarf auch ignoriert werden können, bietet XQuery eine solche Technik noch nicht an. Dies ist daher eine der möglichen Erweiterungen, die in zukünftigen XQuery-Versionen hinzu-kommen können bzw. sollten.

Page 129: XQuery. Eine praxisorientierte Einführung  GERMAN

Implementierungen

129

3 Implementierungen

Im vorigen Kapitel wurden die einzelnen Sprachbestandteile anhand kleiner Beispiele vorgestellt. Wenn Sie diese Beispiele nun am Rechner austesten wollen oder durch die bisherigen Ausführungen bereits zu dem Ergebnis gekommen sind, dass Sie XQuery in einem laufenden Projekt einsetzen wol-len, dann stehen Sie nun vor einer der wichtigsten Entscheidungen in diesem Zusammenhang, nämlich der Auswahl der richtigen XQuery-Implemen-tierung.

Da XQuery eine deklarative Sprache ist, in der nur das gewünschte Ergebnis festgelegt wird, nicht aber der Weg, auf dem dieses Ergebnis erreicht werden soll, kommt der XQuery-Implementierung eine entscheidende Bedeutung zu, insbesondere im Hinblick auf die Performance der Abfragen. Die Geschwin-digkeit sowie der Speicherbedarf, der für die Ausführung einer Abfrage benötigt wird, hängen stark vom Geschick der Entwickler der XQuery-Implementierung ab. Wirft man einen Blick auf Themen und Veröffentli-chungen von XQuery-relevanten Konferenzen und Workshops ([VLDB03], [XIME04], [XSym03]), so fällt auf, dass sowohl im wissenschaftlichen als auch im industriellen Bereich aus diesem Grund viel Arbeit in Abfrageopti-mierung sowie geeignete Speichermodelle für XQuery-Implementierungen investiert wird.

In diesem Kapitel sollen nun einige zum Zeitpunkt der Erstellung dieses Buches bereits verfügbare Implementierungen vorgestellt werden. Bereits mehrfach wurde in diesem Buch auf die Tatsache hingewiesen, dass der XQuery-Standard zum Zeitpunkt der Manuskripterstellung dieses Buches noch nicht endgültig verabschiedet ist. Für die im vorangegangenen Kapitel vorgestellten grundlegenden Sprachbestandteile sollte dies keine gravieren-den Auswirkungen haben, da zu erwarten ist, dass der endgültige Sprachstan-dard sich von der diesem Buch zugrunde liegenden Spezifikations-Version aus dem November 2003 nur in Details unterscheiden wird. Für die Anbieter von XQuery-Implementierungen können solche Details aber eine größere Bedeutung haben. Welcher Anbieter kann es sich schon erlauben, in Detail-aspekten von einem verabschiedeten Standard abzuweichen?

Page 130: XQuery. Eine praxisorientierte Einführung  GERMAN

Ausführung

130

Insbesondere kommerzielle Anbieter halten sich daher zum Zeitpunkt der Erstellung dieses Buches mit einer offiziellen Unterstützung von XQuery in ihren Produkten noch spürbar zurück. Aus diesem Grund finden sich in den folgenden Abschnitten fast ausschließlich frei verfügbare Implementierun-gen, die häufig aus dem universitären Umfeld stammen. Eine Aussage der Art „Unsere Implementierung unterstützt die vorläufige Sprachversion XYZ ohne die folgenden noch nicht implementierten Features: …“ ist in solchen frei verfügbaren Implementierungen eher akzeptabel als in kommerziellen Systemen, bei denen man aufgrund der damit verbundenen Kosten eher ein ausgereiftes Produkt erwartet.

Aber auch bei den im Folgenden vorgestellten Implementierungen kann sich der zum Zeitpunkt der Erstellung dieses Kapitels zugrunde liegende Produkt-umfang durchaus von der aktuellen Version unterscheiden, die Sie auf den zugehörigen Webseiten zu dem Zeitpunkt vorfinden, an dem Sie diese Zeilen lesen. Aus diesem Grund sollte die im Folgenden beschriebene Auswahl von XQuery-Implementierungen auf keinen Fall als umfassende Marktübersicht angesehen werden. Eine aktuelle Suche nach verfügbaren Implementierungen beispielsweise über die W3C-XQuery-Webseite http://www.w3.org/XML/ Query#products sollte daher für ein konkretes Projekt immer durchgeführt werden.

Bevor auf einige ausgewählte Implementierungen näher eingegangen wird, enthält das folgende Kapitel 3.1 eine Auflistung der Ausführungsschritte, die eine Implementierung bei der Abarbeitung eines XQuery-Ausdruckes vor-nimmt. Anschließend werden in Kapitel 3.2 dann einige konkrete Implemen-tierungen vorgestellt. Bei diesen Implementierungen handelt es sich zumeist um Standalone-Implementierungen, die daher insbesondere zu Demo-Zwecken eingesetzt werden können, um XQuery-Ausdrücke auszuführen bzw. die XQuery-Vorgehensweise zu erlernen.

In der Regel werden in Praxisprojekten aber nicht solche Standalone-Anwendungen benötigt, sondern eine Einbindung in die gesamte Projektar-chitektur mit Integrationsmöglichkeiten für externe Systeme. In solchen Pro-jekten wird meist Java als Programmiersprache bzw. als Anwendungsplatt-form eingesetzt, um die unterschiedlichsten Input- und Output-Systeme zu integrieren. Aus diesem Grund spielt eine XQuery-Einbindung in Java-Applikationen eine wichtige Rolle. Viele der bereits verfügbaren XQuery-

Page 131: XQuery. Eine praxisorientierte Einführung  GERMAN

Implementierungen

131

Implementierungen bieten daher die Möglichkeit, XQuery-Ausdrücke inner-halb von Java-Anwendungen auszuführen. Kapitel 3.3 stellt einen dieser Ansätze vor. Neben herstellerspezifischen Lösungen, die zwar fast alle nach demselben Prinzip vorgehen, sich aber trotzdem in konkreten Syntaxaspekten unterscheiden, stellt Kapitel 3.3.2 mit XQJ einen Ansatz vor, einen herstel-lerübergreifenden Standard für die Java-XQuery-Anbindung festzulegen. XQJ steht zwar zum Zeitpunkt der Erstellung dieses Buches erst in einer Early Draft Review-Version zur Verfügung. Aber bereits diese Version zeigt die enge Anlehnung an JDBC als Standard für die Java-Datenbank-Anbin-dung.

3.1 Ausführungsschritte Im Folgenden werden nun die Schritte beschrieben, die bei der Ausführung eines XQuery-Ausdruckes vorgenommen werden. Natürlich ist es jeder XQuery-Implementierung überlassen, auf welchen Wegen sie das Ergebnis eines XQuery-Ausdruckes generiert. Und sicherlich hat auch die Umgebung, in der eine XQuery-Implementierung eingesetzt wird, Einfluss auf die im-plementierten Auswerteschritte. In einer Datenbankumgebung kann bzw. muss sicherlich auf die bereits vorliegenden Techniken insbesondere zur Optimierung (Indizes etc.) zurückgegriffen werden, während in einer reinen Textverarbeitungsumgebung andere Rahmenbedingungen gelten. Trotzdem lassen sich einige grundlegende Verarbeitungsschritte aufführen, die in den meisten XQuery-Implementierungen zu finden sind. Zu unterscheiden sind dabei zwei Gruppen:

1. statische Überprüfungen, die ausschließlich auf der Basis eines XQuery-Ausdruckes sowie weiterer externer Informationen durchgeführt werden können, also ohne die Vorlage der zu verarbeitenden Inputdaten,

2. dynamische Überprüfungen, bei denen die Charakteristika der realen Inputdaten berücksichtigt werden.

Page 132: XQuery. Eine praxisorientierte Einführung  GERMAN

Ausführungsschritte

132

3.1.1 Statische Verarbeitungsschritte Als erster Schritt muss – wie bereits aus anderen Sprachen bekannt – der XQuery-Ausdruck selber analysiert und in ein XQuery-internes Format ge-bracht werden. Ergebnis dieses Parsing-Schrittes ist in der Regel eine baum-artige Darstellung der Abfrage in Form eines so genannten „Abstract Syntax Tree“.

Wie in Kapitel 2 beschrieben wurde, müssen nicht zwingend alle benötigten Informationen in einem einzigen XQuery-Ausdruck vorliegen. Stattdessen können weitere Module eingebunden oder auch externe Typ- und Variablen-definitionen hinzugezogen werden. Alle diese Informationen werden als statischer Kontext bezeichnet. Im Rahmen der statischen Analyse wird u.a. überprüft, ob alle für die Verarbeitung eines Ausdruckes benötigten Informa-tionen (Typangaben, Funktionsnamen etc.) entweder im Ausdruck selber oder an anderer Stelle innerhalb des statischen Kontextes vorliegen. Werden keine statischen Fehler entdeckt, so kann die textuell vorliegende XQuery-Abfrage in ein internes Format überführt werden. Dieses Format wird auch als XQuery-Core-Language bezeichnet. Anstelle einer formalen Beschrei-bung dieser XQuery-Core-Language sei an dieser Stelle nur ein Beispiel dafür aufgelistet, wie diese Darstellung eines XQuery-Ausdruckes aussieht. Als Beispiel wird der folgende bereits in Kapitel 2.2 verwendete XQuery-Ausdruck eingesetzt:

for $b in doc("input/bib.xml")/bib/book

where $b/@year = 2002

return

<buch>

{ $b/title }

</buch>

Die XQuery-Implementierung IPSI, die im folgenden Kapitel 3.2.1 vorge-stellt wird und mit der die Beispiele dieses Buches entwickelt wurden, bietet die Möglichkeit, über die Option „Show Core Query“ (s. Abbildung 3.1 im folgenden Abschnitt 3.2.1) eine Darstellung in der XQuery-Core-Language zu generieren. Für obigen Ausdruck sieht diese Darstellung wie folgt aus:

Page 133: XQuery. Eine praxisorientierte Einführung  GERMAN

Implementierungen

133

for $b in http://www.w3.org/TR/xquery-semantics:

distinct-doc-order(let $fs:sequence :=

http://www.w3.org/TR/xquery-semantics:distinct-doc-

order(let $fs:sequence := doc(data("input/bib.xml"))

return

let $fs:last := count($fs:sequence)

return

for $fs:dot at $fs:position in $fs:sequence

return

child::bib

)

return

let $fs:last := count($fs:sequence)

return

for $fs:dot at $fs:position in $fs:sequence

return

child::book

)

return

if (some $v_0 in data(http://www.w3.org/TR/

xquery-semantics:distinct-doc-order

(let $fs:sequence := $b

return

let $fs:last := count($fs:sequence)

return

for $fs:dot at $fs:position in $fs:sequence

return

attribute::year

)) satisfies some $v_1 in data(2002) satisfies let

$v_2 := http://www.w3.org/TR/xquery-semantics:

convert-operand($v_0, $v_1)

return

let $v_3 := http://www.w3.org/TR/

xquery-semantics:convert-operand($v_1, $v_0)

return

Page 134: XQuery. Eine praxisorientierte Einführung  GERMAN

Ausführungsschritte

134

http://www.w3.org/TR/

xquery-semantics:eq($v_2, $v_3)

)

then

element buch

{

http://www.w3.org/TR/xquery-semantics:

distinct-doc-order(let $fs:sequence := $b

return

let $fs:last := count($fs:sequence)

return

for $fs:dot at $fs:position in

$fs:sequence

return

child::title

)

}

else

()

3.1.2 Dynamische Verarbeitungsschritte Nachdem die statische Analyse eines XQuery-Ausdruckes keine Fehler er-zeugt hat, liegt die Abfrage in einem XQuery-internen Format vor und kann bei Vorlage der zu verarbeitenden Inputdaten ausgeführt werden. Nach dem statischen Kontext, der bei der statischen Analyse ausschließlich auf der Basis des XQuery-Ausdruckes sowie weiterer externer Angaben gebildet wurde, wird nun der dynamische Kontext konstruiert. Dazu werden die In-formationen aus den vorliegenden Inputdaten hinzugezogen, also z.B. kon-krete Datentypen sowie aktuelle Variablenbelegungen.

In Abhängigkeit von der eingesetzten Implementierung können neben der Konstruktion des dynamischen Kontextes auch Optimierungen bezüglich eines konkreten Ausführungsplans für den XQuery-Ausdruck vorgenommen werden. Ein Beispiel hierfür wäre der Einsatz von Indizes bei Zugriff auf in

Page 135: XQuery. Eine praxisorientierte Einführung  GERMAN

Implementierungen

135

einer Datenbank gespeicherte Daten. Weitere Schritte, die im dynamischen Teil einer XQuery-Auswertung vorgenommen werden, betreffen die Ermitt-lung von externen Systemparametern, die nur zur Laufzeit generiert werden können, beispielsweise das aktuelle Datum oder die aktuelle Systemzeit.

3.2 Verfügbare Implementierungen Wie bereits erwähnt, stellen die im Folgenden vorgestellten Implementierun-gen nur eine Auswahl aus den zum Zeitpunkt der Erstellung dieses Buches verfügbaren Implementierungen dar. Die Auswahl ist weder vollständig noch erhebt sie einen Anspruch darauf, die besten Implementierungen zu beinhal-ten. Der Schwerpunkt liegt in diesem Unterkapitel zunächst auf Implementie-rungen, die als Binary von den angegebenen Webseiten heruntergeladen und dann auf dem eigenen Rechner zum Testen von eigenen Beispielen genutzt werden können. Einige Implementierungen sind aber auch online als Demo-Version verfügbar, sodass keine lokale Installation benötigt wird.

Wenn Sie aktuell eine Implementierung suchen, die Sie entweder in einer Testumgebung oder vielleicht auch schon produktiv einsetzen wollen, so kann Ihnen die folgende Liste natürlich schon einige Anhaltspunkte geben. Auf jeden Fall sollten Sie aber die angegebenen Webseiten nutzen, um sich über aktuellere Versionen der Tools17 und vor allem auch über mögliche Lizenzbedingungen zu informieren. Einige der zum Zeitpunkt der Buch-erstellung noch frei verfügbaren Implementierungen könnten in der Zwi-schenzeit lizensierungspflichtig geworden sein oder neben einer freien Versi-on auch in einer erweiterten kommerziellen Version vorliegen18.

Auf jeden Fall sollten Sie auch die Ankündigungen der Anbieter von kom-merziellen Datenbanksystemen verfolgen. Zum Zeitpunkt der Erstellung

17 Dies können beispielsweise auch Anpassungen an aktuellere Versionen des XQuery-Standards sein. 18 Die in Kapitel 3.2.3 beschriebene Saxon-Implementierung ist ein Beispiel für eine solche Implementierung, die bereits zum Zeitpunkt der Erstellung dieses Buches in einer freien Version ohne XML-Schema-Unterstützung sowie einer kommerziellen Version angeboten wird, die dann auch XML-Schema-Unterstützung bietet.

Page 136: XQuery. Eine praxisorientierte Einführung  GERMAN

Verfügbare Implementierungen

136

dieses Buches bieten die meisten bekannten Datenbankhersteller noch keine XQuery-Unterstützung in ihren produktiven Versionen. Stattdessen gibt es beispielsweise für die Oracle-Datenbank nur eine von den Oracle-Webseiten verfügbare Testversion für XQuery-Abfragen. Nach einer endgültigen Verab-schiedung des Standards ist hier aber mit einer breiten Unterstützung auch in Produktivsystemen zu rechnen, da die großen Hersteller in vielen XQuery-Gremien vertreten sind.

3.2.1 IPSI Als erste XQuery-Implementierung sei an dieser Stelle das IPSI-XQ-Tool des Fraunhofer-Instituts [IPS] aufgeführt. Es liegt zum Zeitpunkt der Erstellung dieses Buches in Version 1.3.2 vor und beruht auf der XQuery-Spezifika-tions-Version aus dem November 2003. Die Beispiele dieses Buches wurden mit IPSI erstellt und getestet, sodass die in den Beispielen in Kapitel 2 enthal-tenen Ausgaben und Fehlermeldungen in „IPSI-Format“ angegeben sind.

IPSI kann in mehreren Varianten eingesetzt werden. Für einen Offline-Test kann eine Standalone-Variante von den IPSI-Webseiten heruntergeladen werden. Abbildung 3.1 zeigt die Oberfläche dieser Standalone-Variante.

Im Download-Umfang enthalten ist eine Reihe von Beispiel-XQuery-Skrip-ten mit den zugehörigen Inputdaten. Wie aus Abbildung 3.1 ersichtlich ist, lassen sich neben dem eigentlichen Ergebnis der XQuery-Abfrage auch noch weitere Angaben generieren. Neben importierten XML-Schema-Datentypen ist dies insbesondere auch eine Ausgabe der Abfrage in XQuery-Core-Language-Format. Eine über dieses Tool generierte Ausgabe in diesem For-mat ist im vorangegangenen Kapitel 3.1.1 im Rahmen der statischen Analyse aufgelistet.

Neben dieser Standalone-Variante über eine GUI-Oberfläche ist auch noch eine Kommandozeilenvariante verfügbar, sodass XQuery-Ausdrücke auch auf diesem Weg ausgeführt werden können. Wer keine Software auf seinem Rechner installieren möchte, kann auf die Online-Version von IPSI zurück-greifen.

Page 137: XQuery. Eine praxisorientierte Einführung  GERMAN

Implementierungen

137

Abbildung 3.1: IPSI-Standalone-Oberfläche

Wie einige andere XQuery-Implementierungen auch, so bietet auch IPSI über diesen Weg die Möglichkeit, für einen ersten Einstieg in XQuery einige Tests online durchzuführen. Abbildung 3.2 zeigt die Oberfläche dieser Online-Version.

3.2.2 Qexo Ein anderer Ansatz zur Ausführung von XQuery-Abfragen soll im Folgenden am Beispiel der Qexo-Implementierung illustriert werden. Qexo [QEXO] ist eine Erweiterung des Kawa Frameworks [KAWA] von Per Bothner, das ursprünglich entworfen wurde, um Ausdrücke, die in der funktionalen Pro-grammiersprache Scheme vorliegen, in Java-Bytecode zu übersetzen.

Page 138: XQuery. Eine praxisorientierte Einführung  GERMAN

Verfügbare Implementierungen

138

Abbildung 3.2: IPSI-Online-Demo

Grundlegende Idee von Qexo ist es, XQuery-Ausdrücke in Java-Bytecode zu übersetzen. Vorteil dieser Variante ist, dass dieser Bytecode dann in größeren Java-Projekten integriert werden kann. Kapitel 3.3.1 stellt am Beispiel Qexo diese Idee zur Integration von XQuery und Java noch detaillierter vor. An dieser Stelle folgen daher zunächst nur einige Hinweise zum Einsatz von Qexo.

Qexo kann als Bestandteil des Kawa-Frameworks in Form einer einzelnen Jar-Datei von der Webseite [QEXO] heruntergeladen werden. Zum Zeitpunkt der Erstellung dieses Buches lag dieses Framework in Version 1.7 in der Datei kawa-1.7.jar vor. Über die Option --xquery wird Kawa für die Ver-arbeitung von XQuery-Ausdrücken gestartet. Der XQuery-Ausdruck kann durch die Angabe eines Dateinamens übergeben werden. Im folgenden Bei-spiel

Page 139: XQuery. Eine praxisorientierte Einführung  GERMAN

Implementierungen

139

java -jar kawa-1.7.jar --xquery

Einfuehrungsbeispiel.xquery

enthält die Datei Einfuehrungsbeispiel.xquery den folgenden bereits in Kapi-tel 2 verwendeten XQuery-Ausdruck:

for $b in doc("bib.xml")/bib/book

where $b/@year = 2002

return

<buch>

{ $b/title }

</buch>

Nach obigem Aufruf wird das folgende Ergebnis dieser Abfrage auf der Kon-sole ausgegeben:

<buch>

<title>Tomcat 4x</title>

</buch>

Voraussetzung ist hier, dass sich die Jar-Datei kawa-1.7.jar, das Skript Ein-fuehrungsbeispiel.xquery sowie die Inputdatendatei bib.xml im aktuellen Verzeichnis befinden.

Eine weitere Alternative zur Abarbeitung eines XQuery-Ausdruckes über Qexo ist die folgende interaktive Variante, bei der der XQuery-Ausdruck über die Konsole eingelesen wird. Dazu wird Qexo zunächst wie folgt gestar-tet:

java -jar kawa-1.7.jar --xquery

Es erscheint eine Eingabeaufforderung in der Form

(: <nummer> :)

über die die auszuführenden XQuery-Ausdrücke eingegeben und anschlie-ßend sofort ausgewertet werden können:

Page 140: XQuery. Eine praxisorientierte Einführung  GERMAN

Verfügbare Implementierungen

140

(: 1 :) 1+2

3

(: 2 :) for $i in (1,2,3) return <value>{$i}</value>

<value>1</value><value>2</value><value>3</value>

(: 3 :)

Wie bereits erwähnt, besteht der grundlegende Ansatz von Qexo darin, einen XQuery-Ausdruck in Java-Bytecode zu übersetzen. Dies geschieht über die folgende Syntax:

java -jar kawa-1.7.jar --xquery --main -C

Einfuehrungsbeispiel.xquery

Der in der angegebenen Datei Einfuehrungsbeispiel.xquery enthaltene XQuery-Ausdruck wird in eine Java-Class-Datei Einfuehrungsbeispiel.class umgewandelt. Die Konsolenausgabe nach obigem Aufruf sieht wie folgt aus:

(compiling Einfuehrungsbeispiel.xquery)

Anschließend kann die erzeugte Class-Datei Einfuehrungsbeispiel.class wie folgt über einen normalen Java-Aufruf aufgerufen werden:

>java -cp .;kawa-1.7.jar Einfuehrungsbeispiel

<buch>

<title>Tomcat 4x</title>

</buch>

>

Ein weiteres Beispiel unter Einsatz von Qexo folgt in Kapitel 3.3.1, in dem die Verarbeitung von XQuery-Ausdrücken innerhalb von Java-Anwendungen demonstriert wird.

Page 141: XQuery. Eine praxisorientierte Einführung  GERMAN

Implementierungen

141

3.2.3 Sonstige Nachdem anhand der bisher vorgestellten Implementierungen die grundle-genden Ansätze zur Ausführung von XQuery-Ausdrücken entweder in Stand-alone-Anwendungen, über interaktive Eingabemöglichkeiten oder in Form von Umwandlungen in Java-Bytecode dargestellt wurden, werden im Fol-genden noch einige weitere Implementierungen beschrieben. Die auf den angegebenen Webseiten verfügbare Dokumentation illustriert jeweils die toolspezifischen Aufrufmöglichkeiten, die daher hier nicht detailliert vorge-stellt werden sollen. In jedem Fall lohnt sich ein Blick auf die Webseiten dieser Tools, um einen Überblick über den Umfang der jeweils aktuellen XQuery-Implementierungen zu bekommen.

Galax

Galax [GAL] ist eine Open-Source-Implementierung von XQuery, die unter der Federführung von Mary Fernandez und Jerome Simeon entstanden ist und kontinuierlich an die jeweils neueste Spezifikation der Sprache angepasst wurde. Da Mary Fernandez und Jerome Simeon direkt in der W3C-Arbeits-gruppe zur Spezifikation von XQuery mitarbeiten, ist Galax meist eine der ersten Implementierungen, die die aktuellste Spezifikationsversion unterstüt-zen.

Galax steht – wie die meisten anderen Implementierungen auch – in mehre-ren Ausführungsumgebungen zur Verfügung:

• eine Kommandozeilenversion für den Aufruf von XQuery-Abfragen sowie zum Parsen von XML-Dokumenten,

• eine API-Schnittstelle für mehrere Programmiersprachen (u.a. C und Java),

• eine webbasierte Demo-Version.

Abbildung 3.3 zeigt einen Screenshot dieser Online-Demo-Version. Sie bietet u.a. die Möglichkeit, einzelne Phasen der Abfrageverarbeitung ein- und aus-zuschalten, was vor allem zum Erlernen dieser Features hilfreich sein kann.

Page 142: XQuery. Eine praxisorientierte Einführung  GERMAN

Verfügbare Implementierungen

142

Abbildung 3.3: Galax-Online-Demo

Qizx

Qizx/open [QIZ] ist eine Open-Source-Java-Implementierung von XQuery, deren Vorgehensweise vergleichbar mit der von Qexo ist (s. Kapitel 3.2.2). Qizx/open bietet u.a. die folgenden Einsatzmöglichkeiten:

• Kommandozeilenaufruf durch einen Java-Aufruf mit Integration der Qizx/open-Jar-Datei qizxopen.jar im Classpath und Angabe des XQuery-Ausdruckes über einen Dateinamen.

• Integration in eine Webanwendungs-Umgebung durch Einsatz so ge-nannter XQuery Server Pages.

Page 143: XQuery. Eine praxisorientierte Einführung  GERMAN

Implementierungen

143

Saxon

Saxon [SAX] ist eine in der XML-Welt bereits vor der „XQuery-Zeit“ be-kannte freie Implementierung von XPath- und XSLT-Funktionalität. Seit Version 7.6 bietet Saxon auch XQuery-Unterstützung. Saxon ist ein „Ein-Mann-Projekt“ von Michael H. Kay. Es bietet zwar keine GUI-basierte Ober-fläche, dafür aber die auch aus anderen Implementierungen bekannten Mög-lichkeiten, eine XQuery-Abfrage über einen Kommandozeilenaufruf oder ein Java-API auszuführen.

Beginnend mit Version 8.0 steht Saxon in zwei verschiedenen Varianten zur Verfügung. Über die Sourceforge-Seiten http://saxon.sourceforge.net/ ist weiterhin eine freie Version erhältlich, die aber keine XML-Schema-Unterstützung bietet. Wer eine solche Möglichkeit nutzen will, muss die kommerzielle Version einsetzen [SAX], die eine Erweiterung zur Nutzung der XML-Schema-Features zur Verfügung stellt.

Tamino

Als Beispiel für ein kommerzielles System, das zum Zeitpunkt der Erstellung dieses Buches bereits XQuery-Unterstützung in einer produktiven Version bietet, sei an dieser Stelle das Tamino-System [TAM] der Software AG ge-nannt. Kernbestandteil des Tamino-XML-Servers ist eine native XML-Datenbank. Native XML-Datenbnken zeichnen sich gegenüber den bekann-ten relationalen Datenbanken, die um XML-Features erweitert wurden, da-durch aus, dass ihr internes Speichermodell unmittelbar auf die Speicherung von XML-Daten ausgerichtet ist. Im Unterschied dazu werden XML-Daten in relationalen Systemen in der Regel in den auf das relationale Tabellenfor-mat abgestimmten flachen Speicherstrukturen abgelegt, sodass die hierarchi-sche Struktur eines XML-Dokumentes nicht ausgenutzt werden kann.

Neben der direkten Speicherung in der Tamino-eigenen XML-Datenbank lassen sich über den Tamino-XML-Server auch extern gespeicherte XML-Dokumente einbinden. Als Abfragesprache für den Tamino-XML-Server steht XQuery zur Verfügung. Neben den grundlegenden Funktionen aus der XQuery-Spezifikation bietet die XQuery-Implementierung in Tamino zusätz-lich noch Textverarbeitungsfunktionen sowie Möglichkeiten zum Update von XML-Daten an.

Page 144: XQuery. Eine praxisorientierte Einführung  GERMAN

Verfügbare Implementierungen

144

3.2.4 BumbleBee Auch wenn bereits mehrere freie und kommerzielle Implementierungen von XQuery verfügbar sind, so haben diese meist den Nachteil, dass entweder noch nicht der volle Umfang der aktuellen XQuery-Spezifikation unterstützt wird oder der Funktionsumfang bei neueren Versionen des Tools verändert wird. Ein weiterer Nachteil können herstellerspezifische Erweiterungen sein, die über den Standard hinausgehen. Diese bieten zwar in der Regel einen interessanten Zusatznutzen (beispielsweise durch die Hinzunahme von Up-datemöglichkeiten), können aber zu einer Bindung an den jeweiligen Herstel-ler führen.

Sowohl zum Erlernen einer neuen Sprache als auch für einen produktiven Einsatz sind solche Bindungen an einen bestimmten Hersteller nicht immer wünschenswert. Wer sich auf der Basis eines einzelnen Tools in eine Sprache einarbeitet, läuft Gefahr, durch fehlerhaft oder überhaupt nicht implementier-te Features bereits in der Lernphase einen unvollständigen Überblick über die Sprache zu erhalten. In produktiven Projekten muss sichergestellt sein, dass die verwendeten XQuery-Ausdrücke standardkonform sind, um nicht bei einem späteren Herstellerwechsel bei der eingesetzten XQuery-Implemen-tierung erhöhte Migrationsaufwände einplanen zu müssen.

Wer aus diesen Gründen eine herstellerunabhängige Testumgebung für seine XQuery-Skripte sucht, wird bei BumbleBee [BUMB] fündig werden. Bum-bleBee ist vergleichbar mit der Rolle, die JUnit in der Java-Entwicklung spielt. Über BumbleBee können Testskripte erzeugt werden, in denen neben der eigentlichen XQuery-Abfrage angegeben wird, welche Inputdaten ver-wendet werden sollen und wie das gewünschte Ergebnis aussehen soll. Ein solches Testskript kann dann über BumbleBee gegen mehrere XQuery-Implementierungen getestet werden. Ergebnis eines BumbeBee-Durchlaufes ist dann eine Liste von pro verwendeter XQuery-Implementierung aufgetre-tenen Fehlern. Zum Zeitpunkt der Erstellung dieses Buches bietet Bumble-Bee Adapter für insgesamt sieben freie und kommerzielle XQuery-Implementierungen an, darunter auch die in diesem Kapitel vorgestellten Implementierungen

Page 145: XQuery. Eine praxisorientierte Einführung  GERMAN

Implementierungen

145

• IPSI-XQ • Qexo • Qizx • Saxon

Während der Lernphase kann durch die sukzessive Erstellung von Testskrip-ten auf der Basis der von BumbleBee generierten Fehlermeldungen eine Einarbeitung in die Sprache XQuery erfolgen. Außerdem kann bei Verab-schiedung einer aktualisierten XQuery-Spezifikation auf der Basis der erstell-ten Testskripte ein Update auf die neue Version durchgeführt werden.

3.3 Java-Anbindung Aus der Vorstellung einzelner Implementierungen im vorigen Abschnitt ist bereits ersichtlich, dass eine Möglichkeit zur Einbindung einer XQuery-Implementierung in ein Software-System der Einsatz von Java ist. Innerhalb einer Java-Anwendung kann eine XQuery-Abfrage über spezielle Java-Klassen definiert und ausgeführt werden. Die Abfrageergebnisse können dann entweder ausgegeben oder weiterverarbeitet werden. Auf diese Weise wird der Tatsache Rechnung getragen, dass Abfragen auf XML-Dokumenten in realen Projekten in der Regel nicht als Standalone-Anwendung benötigt werden, sondern meist in einen bereits bestehenden Systemkontext einge-bunden werden müssen. Für diese Aufgabe der Systemintegration ist Java aufgrund der Vielzahl der mit dieser Sprache zur Verfügung stehenden Mög-lichkeiten zur Anbindung an externe Systeme sehr gut geeignet.

In den folgenden Abschnitten werden nun zwei Ansätze zur Java-XQuery-Integration vorgestellt. Eine Möglichkeit sieht den Einsatz von herstellerspe-zifischen Klassen vor. Wie den vorangegangenen Tool-Beschreibungen zu entnehmen ist, bieten die meisten Hersteller von XQuery-Implementierungen diese Möglichkeit an. Ein zum Zeitpunkt der Erstellung dieses Buches noch in der Entwicklung befindlicher Ansatz ist der Einsatz eines herstellerüber-greifenden Standards für diese Java-Anbindung. Dieser entsteht unter der Bezeichnung XQJ und soll eine Art „JDBC für XQuery“ werden.

Page 146: XQuery. Eine praxisorientierte Einführung  GERMAN

Java-Anbindung

146

3.3.1 Herstellerspezifische Lösungen Die herstellerspezifischen Lösungen zur Einbindung von XQuery-Ausdrü-cken in Java-Applikationen gehen in der Regel nach demselben Prinzip vor, unterscheiden sich allerdings in Detailfragen, z.B. in Namenskonventionen. Dies hat natürlich den großen Nachteil, dass Sourcecode nicht portabel ist, d.h. eine Java-Applikation, die auf der Basis der Java-Klassen aus einer XQuery-Implementierung A entwickelt wurde, muss bei Wechsel auf eine XQuery-Implementierung B angepasst werden. Der im folgenden Kapitel 3.3.2 vorgestellte XQJ-Standard soll dieses Problem in Zukunft lösen.

Aufgrund der vergleichbaren Vorgehensweise bei den einzelnen Implemen-tierungen wird an dieser Stelle nur ein Beispiel für eine einfache Java-Anbindung vorgestellt. Dazu wurde die zuvor bereits vorgestellte Qexo-Implementierung ausgewählt. Diese bietet eine Reihe von Java-Klassen an, mit der die Verbindung von XQuery-Ausdrücken zu den restlichen Java-Konstrukten realisiert werden kann. Das folgende Beispiel zeigt die grundle-gende Vorgehensweise:

import gnu.xquery.lang.XQuery;

public class XQueryDemo

{

public static void main (String[] args) throws

Throwable

{

XQuery xq = new XQuery();

String xq_ausdruck = args[0];

Object xq_ergebnis = xq.eval(xq_ausdruck);

System.out.println("Abfrage:" + xq_ausdruck);

System.out.println("Ergebnis:" + xq_ergebnis);

}

}

Über die Klasse XQuery aus dem gnu.xquery.lang-Package von Qexo kann ein in diesem Beispiel als Aufrufparameter eingegebener XQuery-Ausdruck durch Aufruf der eval-Methode

Page 147: XQuery. Eine praxisorientierte Einführung  GERMAN

Implementierungen

147

Object xq_ergebnis = xq.eval(xq_ausdruck);

ausgewertet werden. In diesem einfachen Beispiel erfolgt ausschließlich eine Ausgabe des Ergebnisses auf der Konsole. Durch Einbindung der Jar-Datei kawa-1.7.jar mit den benötigten Qexo-Klassen (s. Kapitel 3.2.2) in den Classpath kann die Applikation wie folgt compiliert und ausgeführt werden:

> javac -classpath .;kawa-1.7.jar -g XQueryDemo.java

> java -cp .;kawa-1.7.jar XQueryDemo "for $i in (1,2,3)

return <value>{$i}</value>"

Abfrage:for $i in (1,2,3) return <value>{$i}</value>

Ergebnis:<value>1</value>, <value>2</value>,

<value>3</value>

Die Qexo-Klassen stellen weitere Funktionen zur Ein- und Ausgabe von XQuery-Ausdrücken und deren Ergebnissen sowie zur Weiterverarbeitung dieser Ergebnisse zur Verfügung.

3.3.2 XQJ Während die herstellerspezifischen Lösungen zur Einbindung einer XQuery-Abfrage in ein Java-Programm zwar in der Regel auf demselben Prinzip beruhen, unterscheiden sie sich aber so signifikant beispielsweise in Na-menskonventionen, dass ein Einsatz eines unveränderten Sourcecodes in zwei verschiedenen Implementierungen nicht möglich ist. Genau diese Mög-lichkeit ist aber ein wichtiger Vorteil beim Einsatz von JDBC zur Anbindung von Java an relationale Datenbanken.

JDBC für relationale Datenbanken

Wie bereits mehrfach in diesem Buch sei auch an dieser Stelle wieder ein Vergleich der XML-Welt mit der Welt der relationalen Datenbanken erlaubt. Da sich SQL als Abfragesprache für relationale Datenbanken etabliert hat, war eine Einbindung von SQL-Ausdrücken in Java-Sourcecode einer der

Page 148: XQuery. Eine praxisorientierte Einführung  GERMAN

Java-Anbindung

148

wichtigsten Bestandteile bereits in den ersten Java-Versionen. Auch wenn es mit SQLJ einen Standard gibt, der eine direkte Einbettung der SQL-Statements in Java-Sourcecode ermöglicht, indem diese Statements vor dem eigentlichen Java-Compiler-Aufruf durch einen SQLJ-Precompiler vorverar-beitet und so in „normales“ Java-Format gebracht werden, war und ist JDBC für diese Aufgabe der am weitesten bekannte Standard.

Inzwischen wird zwar insbesondere in großen Enterprise-Anwendungen meist JDBC nicht mehr direkt programmiert. Stattdessen gibt es beispiels-weise mit JDO (Java Data Objects) oder EJB-CMP (Enterprise Java Beans – Container Managed Persistence)-Standards, die zwar auf JDBC aufbauen, dem Entwickler aber einen Großteil der manuellen Codierungsarbeit abneh-men. JDBC wird aber auch in Zukunft die Grundlage für eine Java-Anbindung an relationale Datenbanken bleiben.

Einer der entscheidenden Vorteile von JDBC ist die Herstellerunabhängig-keit. Ein einfaches JDBC-Programm der folgenden Art

ds = (DataSource) ctx.lookup("jdbc/Test_DB");

Connection conn = ds.getConnection(user, password);

// Statement anlegen

Statement stmt = conn.createStatement();

// Statement ausfuehren

resSet = stmt.executeQuery("select bch_nr, bch_isbn,

bch_titel from buch");

// Ergebnis ausgeben

while (resSet.next()) {

System.out.println("Nr:" + resSet.getInt(1));

System.out.println("ISBN:" +

resSet.getString("bch_isbn"));

System.out.println("Titel:" + resSet.getString(3));

}

stmt.close();

Page 149: XQuery. Eine praxisorientierte Einführung  GERMAN

Implementierungen

149

kann problemlos19 mit den entsprechenden Produkten (JDBC-Treiber, Daten-bank) unterschiedlicher Hersteller eingesetzt werden. Genau an dieser Stelle sieht man also unmittelbar einen der Unterschiede zu den im vorigen Ab-schnitt vorgestellten herstellerspezifischen Lösungen zur Einbindung von XQuery-Ausdrücken in Java-Anwendungen.

Wenn XQuery also wirklich gemäß dem bereits mehrfach zitierten Werbe-slogan „das SQL des 21. Jahrhunderts“ werden will, dann besteht an dieser Stelle noch erheblicher Nachholbedarf, denn viele Anwendungen werden in Java realisiert, sodass eine Abfragesprache zwingend auch ihre Stärken in Verbindung mit Java zum Ausdruck bringen muss. Diese derzeitige Schwä-che von XQuery wurde bereits vor der offiziellen Verabschiedung der ersten XQuery-Version erkannt. Da trotz dieser Schwäche aber die grundlegende Bedeutung von XQuery für die XML-Welt außer Frage stand, haben sich mehrere Hersteller von XML-Produkten bzw. Technologien, die XML in immer stärkerem Maße unterstützen, zu einer Arbeitsgruppe zusammenge-schlossen, die als JSR 225 XQJ entwickeln, eine Art „JDBC für XQuery“.

XQJ für XML-Daten

Zum Zeitpunkt der Erstellung dieses Buches liegt nur eine erste Early Draft Review-Version der XQJ-Spezifikation vor [XQJ]. Diese enthält aufgrund des frühen Status naturgemäß noch keine Details sowie keine Garantie, dass die endgültige Version sich nicht noch signifikant von dieser ersten Version unterscheidet. Trotzdem lässt sich an dem folgenden aus [XQJ] übernomme-nen Sourcecode-Auszug bereits die angestrebte Struktur von XQJ-Anwen-dungen und insbesondere die enge Anlehnung an die JDBC-Vorgehensweise erkennen:

// establish a connection to the XQuery engine

XQConnection conn = xqds.getConnection();

// create an expression object that is later used

// to execute an XQuery expression

19 Probleme bei der Portierung entstehen in der Regel erst dann, wenn herstellerspezi-fische JDBC-Erweiterungen verwendet werden, die dann natürlich nicht ohne zusätz-lichen Migrationsaufwand portiert werden können.

Page 150: XQuery. Eine praxisorientierte Einführung  GERMAN

Java-Anbindung

150

XQExpression expr = conn.createExpression();

// The XQuery expression to be executed

String es = "for $n in fn:doc('catalog.xml')//item" +

" return fn:data($n/name)";

// execute the XQuery expression

XQResultSequence result = expr.executeQuery(es);

// process the result (sequence) iteratively

while (result.next())

{

// retrieve the current item of the sequence as a

// String

String str = result.getString();

System.out.println("Product name: " + str);

}

// free all resources allocated for the result

result.close();

// free all resources allocated for the expression

expr.close();

// free all resources allocated for the connection

conn.close();

Wie bei JDBC-Anwendungen soll auch bei XQJ-Anwendungen ein Data-Source-Objekt – im obigen Beispiel das Objekt xqds – die Verbindung zur XML-Datenquelle kapseln. Die weiteren Schritte und Klassenbezeichnungen sollen an dieser Stelle nicht weiter beschrieben werden, sind aber bereits mit grundlegendem JDBC-KnowHow offensichtlich.

Abbildung 3.4 zeigt die angestrebte Architektur von XQJ-Anwendungen. Aus einer Java-Anwendung heraus wird über XQJ-Funktionen ein XQuery-Ausdruck an eine XML-Datenquelle bzw. ein XQDataSource-Objekt über-geben. Dieses kapselt die XML-Datenquelle, die eine relationale Datenbank mit XML-Views, eine oder mehrere XML-Dateien oder jede andere Daten-quelle sein kann, solange sie ihre Daten in XML-Format zur Verfügung stellt. Das Ergebnis des XQuery-Ausdruckes liegt in XML vor und kann mit den XQJ-Methoden in der Java-Anwendung verarbeitet werden.

Ohne näher auf Details von XQJ eingehen zu wollen, lässt sich bereits an-hand dieser ersten Public Draft Review-Version von [XQJ] das enorme Po-

Page 151: XQuery. Eine praxisorientierte Einführung  GERMAN

Implementierungen

151

tenzial dieses kommenden Standards erkennen. Wenn dieser Standard konse-quent weiterentwickelt und von den großen Herstellern unterstützt wird, steht einem Erfolg beim Einsatz von XQuery in Verbindung mit Java-Anwen-dungen eigentlich nichts mehr im Wege. Mit Interesse verfolgt werden sollte die Weiterentwicklung von XQJ unter anderem auch unter der Fragestellung, ob auch ein einziges DataSource-Objekt sowohl für XQuery-Abfragen auf XML-Daten als auch für SQL-Abfragen auf relationalen Datenbanken einge-setzt werden kann. Mit Hinblick auf die in Praxisprojekten häufig vorzufin-dende Koexistenz von XML- und relationalen Daten wäre diese Möglichkeit ein weiterer Meilenstein im Hinblick auf die Integration von XML- und rela-tionaler Datenbank-Welt.

Abbildung 3.4: XQJ-Architektur

Page 152: XQuery. Eine praxisorientierte Einführung  GERMAN
Page 153: XQuery. Eine praxisorientierte Einführung  GERMAN

Anwendungen

153

4 Anwendungen

Zum Abschluss dieses Buches folgen noch ein kurzes Kapitel über mögliche Anwendungen von XQuery sowie eine Zusammenfassung. Im Vergleich zu den vorigen Kapiteln über die Sprachentstehung, die einzelnen Sprachbe-standteile sowie erste verfügbare Implementierungen ist dieses Kapitel das kürzeste. Der Grund dafür liegt darin, dass es zum derzeitigen frühen Zeit-punkt in der Entstehungsgeschichte der Sprache XQuery naturgemäß noch keine umfangreiche Liste von Erfolgsgeschichten in Form von Praxisprojek-ten geben kann, in denen XQuery bereits über einen längeren Zeitraum er-folgreich eingesetzt wurde. Stattdessen stellen die im Folgenden aufgeführten Anwendungsgebiete eher einen Blick in die Zukunft dar. In welchen Berei-chen hat XQuery das Potenzial, produktiv eingesetzt zu werden?

Neben den durchaus positiven Aussichten über mögliche Einsatzgebiete darf aber natürlich auch eine kritische Betrachtung der Probleme nicht fehlen, die mit einem XQuery-Einsatz verbunden sein können. Solche „Probleme“ wer-den in erster Linie durch fehlende Features auftreten. Zum derzeitigen frühen Zeitpunkt steht XQuery sicherlich noch nicht in der endgültigen Version zur Verfügung. Daher wird es sowohl beim Austesten als auch bei einem mögli-chen produktiven Einsatz von XQuery immer wieder Situationen geben, in denen der zur Verfügung stehende Sprachumfang nicht ausreichend sein wird. In dieser Hinsicht wird auch XQuery keine Sonderstellung einnehmen. Auch bei anderen Sprachen ist der derzeitig verfügbare Sprachumfang erst im Laufe der Zeit gewachsen. Als Beispiel sei hier die Sprache Java genannt, die zwar mit ihrer ersten Version bereits viele Freunde durch damals ganz neue Features (z.B. Plattformunabhängigkeit) gewinnen konnte. Heutige große Java-Projekte wären aber ausschließlich mit den bereits in Java 1.0 verfügba-ren Sprachbestandteilen kaum vorstellbar.

Page 154: XQuery. Eine praxisorientierte Einführung  GERMAN

Systemintegration

154

4.1 Systemintegration XML als Datenaustauschformat zwischen Anwendungen spielt bereits heute eine wichtige Rolle im Bereich der Systemintegration. Aufgrund seiner Platt-formunabhängigkeit bietet XML die Chance, innerhalb einer heterogenen Systemarchitektur mit Anwendungen, die auf verschiedenen Plattformen laufen und/oder in verschiedenen Sprachen implementiert wurden, ein von allen Systemen unterstütztes Datenformat zu definieren, über das sich die Systeme „unterhalten“ können. An den Schnittstellen der einzelnen Systeme wird dabei häufig die Aufgabe anfallen, interne Daten zu selektieren und gleichzeitig in das gemeinsame XML-Format zu transformieren – also eine Aufgabe, für die XQuery aufgrund seiner Abfrage- und Transformationsmög-lichkeiten sehr gut geeignet ist.

Im Rahmen einer solchen Systemintegration kann XQuery insbesondere seine Stärke ausspielen, auf unterschiedliche Inputdaten parallel zugreifen zu können. Wenn also Stammdaten in einer relationalen Datenbank vorliegen und die darauf basierenden dynamischen Daten in XML-Dateien bzw. XML-Streams vorliegen, so lassen sich beide Datenquellen in XQuery-Abfragen verbinden, falls für beide Quellen entsprechende XQuery-Inputadapter zur Verfügung stehen. Ein Problem bei dieser Konstellation und einer Vielzahl von zu verknüpfenden externen Datenquellen kann das Datentransfervolu-men darstellen, falls die komplette Abfrage an einer Stelle, nämlich in der eingesetzten XQuery-Implementierung, vorgenommen werden muss. Für die Zukunft sind hier also sowohl bei der Weiterentwicklung des XQuery-Sprachstandards als auch bei der Erstellung von XQuery-Engines Ideen für eine verteilte Datenverarbeitung erforderlich.

4.2 Webanwendungen Wie in Kapitel 3.3 bereits erwähnt, bieten die meisten derzeit schon verfüg-baren XQuery-Implementierung eine Möglichkeit an, XQuery-Abfragen innerhalb von Java-Anwendungen einzusetzen. Ein Einsatzgebiet, in dem XQuery Chancen eingeräumt werden, sich als neuer Standard durchzusetzen, ist also die Integration von XML-Techniken in Java. Während dies derzeit noch über spezielle Java-APIs beispielsweise zur Verarbeitung von DOM-Strukturen vorgenommen werden muss, wird XQuery hier spätestens dann

Page 155: XQuery. Eine praxisorientierte Einführung  GERMAN

Anwendungen

155

ins Spiel kommen, wenn der in Kapitel 3.3.2 beschriebene XQJ-Standard als eine Art „JDBC für XQuery“ bzw. „JDBC für XML-Daten“ verabschiedet und von den wichtigsten Anbietern unterstützt wird.

Ein weiteres Einsatzgebiet von XQuery ist der Einsatz in Form von Servlets. Auch hierzu bieten derzeit bereits einige Implementierungen Tools an. Die Qexo-Implementierung (s. Kapitel 3.2.2) ermöglicht beispielsweise über einen speziellen Parameter -servlet in der folgenden Form

java –jar kawa-1.7.jar –xquery –servlet –C

<xquery_skript>

eine Übersetzung eines XQuery-Skriptes in eine Servlet-Klasse, die dann über die bekannten Techniken beispielsweise in der Tomcat-Engine innerhalb von Webapplikationen genutzt werden kann. Auch im Webservice-Umfeld, in dem XML eine entscheidende Rolle spielt, sind Anwendungsgebiete für XQuery denkbar.

Aber nicht nur in Form von Servlets oder innerhalb von Webservice-Anwendungen kann XQuery in Webapplikationen eingesetzt werden, son-dern auch „hinter den Kulissen“ solcher Projekte bei der Auswertung von Logdateien. Immer mehr setzt sich nämlich der Trend durch, Logdateien im XML-Format anzulegen. Wer dort dann zwecks Fehlersuche oder Erstellung von Zugriffsstatistiken eine Abfrage auf diesen XML-Daten durchführen muss, wird sicherlich den Einsatz der XML-Abfragesprache XQuery in Er-wägung ziehen. Eine weitere Möglichkeit besteht darin, nicht alle im XML-Format aus diversen Applikationen ausgegebenen Logging-Informationen in Dateiform zu speichern, sondern über XQuery-Skripte online nur diejenigen Informationen auszufiltern, die tatsächlich relevant sind.

4.3 Fazit Die aufgeführten Anwendungsgebiete machen XQuery also für die Zukunft sehr interessant. Bereits mehrfach sind in diesem Buch aber auch Kritikpunk-te am aktuellen XQuery-Standard aufgeführt worden, die an dieser Stelle nochmals zusammengefasst werden sollen. Was fehlt also in XQuery 1.0 noch?

Page 156: XQuery. Eine praxisorientierte Einführung  GERMAN

Fazit

156

• Updatemöglichkeiten: Dies ist der in der Literatur am häufigsten genann-te Kritikpunkt an der ersten XQuery-Version. Alle in diesem Buch auf-geführten Beispiele waren reine Read-Only-Beispiele. Es ist zwar über XQuery möglich, eigene Formate für die Konstruktion eines Abfrageer-gebnisses innerhalb der Return-Klausel zu verwenden. Eine Veränderung der Inputdaten dagegen ist nicht möglich. Von den Mitgliedern der W3C-XQuery-Arbeitsgruppe ist daher bereits verkündet worden, dass Update-Features ein zentraler Bestandteil der nächsten XQuery-Version 1.1 oder 2.0 werden sollen. Wenn XQuery wirklich innerhalb der XML-Welt eine ähnliche Bedeutung wie SQL in der relationalen Welt bekom-men soll, so sind solche Update-Möglichkeiten auch zwingend erforder-lich, denn wer kann sich schon ein reines Read-Only-SQL ohne Update-, Insert- und Delete-Befehl vorstellen?

• Fortgeschrittene Textoperationen, insbesondere Suchoperationen für den Einsatz von XML im Rahmen von Dokumentenverarbeitung.

• Ausführlichere Fehlerbehandlungsmöglichkeiten analog zu den try-catch-Blöcken in anderen Sprachen (s. Kapitel 2.8).

• Sicherheitsmechanismen, die spätestens dann benötigt werden, wenn XQuery in Praxisprojekten mit sensiblen Daten eingesetzt werden soll.

Zu hoffen bleibt, dass eine entsprechend erweiterte XQuery-Version mög-lichst bald zur Verfügung gestellt wird, da ansonsten die Gefahr besteht, dass jeder Anbieter einer XQuery-Implementierung hierzu eigene herstellerspezi-fische Erweiterungen einführt. Diese bringen das Problem, dass ein Aus-tausch der eingesetzten XQuery-Implementierung mit entsprechend höherem Portierungsaufwand verbunden ist. Ein Beispiel dafür ist die bereits erwähnte Möglichkeit, XQuery-Ausdrücke in Java-Anwendungen zu nutzen. Dies bietet zwar inzwischen beinahe jede verfügbare Implementierung an, aller-dings immer mit einer eigenen Syntax.

Ein wichtiger Aspekt jeder neuen Sprache ist deren Komplexität und die damit verbundenen Schwierigkeiten beim Erlernen einer Sprache. Wenn Sie dieses Buch vollständig durchgearbeitet haben, dann haben Sie sicherlich bereits eine eigene Meinung zu der Frage, wie schwierig XQuery zu erlernen ist. Eine wichtige Rolle bei dieser Einschätzung spielen natürlich die Vor-kenntnisse. Wer noch nie direkt mit XML gearbeitet hat, wird sicherlich

Page 157: XQuery. Eine praxisorientierte Einführung  GERMAN

Anwendungen

157

mehr Zeit zur Einarbeitung in die „XML-Denkweise“ und damit auch in die XQuery-Vorgehensweise benötigen als jemand, der die zugrunde liegenden Techniken XPath und XML-Schema bereits kennt. Grundsätzlich lässt sich feststellen, dass XQuery natürlich die Komplexität dieser beiden zugrunde liegenden Standards erbt. Wer XQuery einsetzen will, sollte insbesondere die Möglichkeiten von XPath 2.0 kennen bzw. erlernen, denn Schätzungen zu-folge besteht XQuery zu 80% aus XPath 2.0.

Wer XQuery anwenden will und über entsprechende Grundkenntnisse in den vorgestellten XML-Standards verfügt, für den sollte das Erlernen der benötigten XQuery-Techniken kein unüberwindbares Hindernis darstellen. Richtig schwierig wird das Ganze eigentlich nur dann, wenn man selber eine XQuery-Implementierung erstellen will, denn dann führt kein Weg an einem intensiven Studium der zugrunde liegenden theoretischen Spezifikationen zum Datenmodell sowie der formalen Semantik vorbei.

Bei der Abgrenzung gegenüber den anderen XML-Standards lässt sich fest-stellen, dass XQuery seine Stärken eher im Bereich XML-Datenverarbeitung hat, während XSLT mehr zur XML-Dokumentenverarbeitung eingesetzt wird.

Mehrfach wurde in diesem Buch der Vergleich von XQuery mit SQL er-wähnt. Wie am Anfang des Buches beschrieben, war eine der ersten Ideen bei der Entwicklung einer XML-Abfragesprache eine entsprechende Erweiterung von SQL. Auch wenn es solche Erweiterungen beispielsweise in Form des SQL/XML-Standards sowie weiterer herstellerspezifischer Features inzwi-schen gibt, so wurde aufgrund der grundlegend verschiedenen internen Struk-tur von XML- und relationalen Daten bewusst eine neue Sprache definiert. Wie vor allem im Kapitel über die FLWOR-Ausdrücke leicht zu erkennen ist, haben viele XQuery-Sprachbestandteile Ähnlichkeiten mit entsprechenden SQL-Features. Wie kann XQuery also im Vergleich zu SQL positioniert werden?

Derzeit liegt SQL naturgemäß in Bedeutung und Marktanteilen noch weit vor XQuery. Der Grund dafür dürfte aber nicht darin liegen, dass SQL unbedingt

Page 158: XQuery. Eine praxisorientierte Einführung  GERMAN

Fazit

158

besser als XQuery ist20, sondern weil der „Zielgruppenumfang“ sehr unter-schiedlich ist: Die Menge von relational gespeicherten Daten als Zielgruppe von SQL ist derzeit in Praxisprojekten noch höher als die Zielgruppe XML-Daten für XQuery.

Wie wird die IT-Welt aber in fünf oder zehn Jahren aussehen? Auch wenn ein solcher Zeitraum in der schnelllebigen IT-Welt ein nur schwer vorherseh-barer Zeitraum ist, so muss man sicherlich kein Prophet sein, um vorauszusa-gen, dass eine XML-basierte Datenübertragung und eine XML-basierte Da-ten- und Dokumentenspeicherung eine immer höhere Bedeutung erlangen und die relationale Speicherung sicherlich irgendwann überholen werden. Wenn XQuery sich als Standard für eine XML-Abfragesprache durchsetzt, dann wird XQuery spätestens zu diesem Zeitpunkt auch SQL als Standard-Abfragesprache für Daten aller Art ablösen.

Ist es also denkbar, dass Informatikstudenten in einigen Jahren standardmä-ßig zunächst in XQuery unterrichtet werden und der „alte Standard“ SQL nur noch in Spezialveranstaltungen eingesetzt wird? Werden reine SQL-Spezia-listen also in mittlerer bis ferner Zukunft zu einer Minderheit gehören, die sich ausschließlich um die Pflege alter Anwendungen kümmern wird, die noch nicht auf den neuen Standard XQuery umgestellt worden sind? Antwor-ten auf diese Fragen sollen und können an dieser Stelle natürlich (noch) nicht gegeben werden, denn Aussagen dazu wären zum Zeitpunkt der Erstellung dieses Buchmanuskriptes, an dem die erste offizielle XQuery-Sprachversion noch nicht einmal verabschiedet ist, in keiner Weise belegbar und hätten daher eine ausschließlich marketing-lastige Bedeutung. Ich hoffe aber, dass Sie durch das Studium dieses Buches und mögliche erste eigene Experimente mit der neuen Sprache XQuery neugierig geworden sind und die weitere Entwicklung von XQuery mit Interesse verfolgen werden. Denn aufgrund der beschriebenen Perspektiven und Einsatzmöglichkeiten kann XQuery durch-aus zu dem werden, was derzeit schon viele der neuen Sprache voraussagen, nämlich zu „XQuery – dem SQL des 21.Jahrhunderts“. 20 Eine solcher Vergleich wäre natürlich auch unfair, denn dabei würde man einen über viele Jahre gewachsenen Standard (SQL) mit einem noch nicht einmal endgültig verabschiedeten Standard (XQuery) vergleichen.

Page 159: XQuery. Eine praxisorientierte Einführung  GERMAN

Literatur

159

Literatur

[Bru04] Michael Brundage, XQuery – The XML Query Language,

Addison Wesley 2004

[BUMB] BumbleBee: http://xquery.com/bumblebee/

[FIT03] Michael Fitzgerald: Learning XSLT, O’Reilly 2003

[GAL] Galax-Implementierung: http://www.galaxquery.org/

[IPS] IPSI-XQ-Implementierung:

http://www.ipsi.fraunhofer.de/oasys/projects/ipsi-xq/overview_d.html

[Kat03] Howard Katz (Hrsg.) u.a.: XQuery from the Experts – A Guide to the

W3C XML Query Language, Addison-Wesley 2003

[KAWA] Kawa Framework: http://www.gnu.org/software/kawa/

[QEXO] Qexo – The GNU Kawa implementation of XQuery

http://www.gnu.org/software/qexo

[QIZ] qizx/open-Implementierung: http://www.xfra.net/qizxopen/

[SIM02] John E. Simpson: XPath and XPointer, O’Reilly 2002

[SAX] Saxon-Implementierung: http://www.saxonica.com/

[TAM] Tamino: http://www2.softwareag.com/de/products/tamino/default.asp

[VDF02] Eric van der Vlist: XML Schema, O’Reilly 2002

[VLDB03] Proceedings of the 29th International Conference on Very Large

DataBases, Morgan Kaufmann Publishers 2003

[XIME04] Proceedings of the First International Workshop on XQuery

Implementation, Experience and Perspectives <XIME-P/>,

ACM SIGMOD 2004

[XQDM] XQuery 1.0 and XPath 2.0 Data Model W3C Working Draft

12.Nov 2003, http://www.w3.org/TR/xpath-datamodel/

[XQF] XQuery 1.0 and XPath 2.0 Functions and Operators W3C

Working Draft 12.Nov 2003, http://www.w3.org/TR/xpath-functions/

Page 160: XQuery. Eine praxisorientierte Einführung  GERMAN

Literatur

160

[XQJ] XQuery API for Java (XQJ) 1.0 Specification Version 0.2.1

(Early Draft Review) W3C Working Draft 10.May 2004,

http://jcp.org/aboutJava/communityprocess/edr/jsr225/index.html

[XQR] XQuery Requirements W3C Working Draft 12.Nov 2003,

http://www.w3.org/TR/xquery-requirements/

[XSD] XML Schema Part 2: Datatypes W3C Recommendation 02 May 2001

http://www.w3.org/TR/xmlschema-2/

[XSym03] Database and XML Technologies – First International XML

Database Symposium, XSym 2003, Springer-Verlag LNCS 2824

Page 161: XQuery. Eine praxisorientierte Einführung  GERMAN

Autor

161

Autor

Rudolf Jansen

Rudolf Jansen ist freiberuflicher Software-Entwickler und Fachautor aus Aachen. Er hat mehrjährige praktische Erfahrungen in den Bereichen Oracle, Java, C++ und XML. Er ist Autor der im Software & Support Verlag erschienenen Bücher „Oracle, Java, XML: Integration in Oracle 9i; Architekturansätze für die Praxis“ und „Java Persistenz-Strate-gien“ und schreibt Artikel für Fachzeitschrif-ten, u.a. für das Java Magazin und das XML Magazin. Außerdem ist er als Referent auf Entwicklerkonferenzen tätig und bietet Schu-lungen zu den genannten Themen an.

Sie erreichen ihn unter der E-Mail-Adresse [email protected].

Page 162: XQuery. Eine praxisorientierte Einführung  GERMAN
Page 163: XQuery. Eine praxisorientierte Einführung  GERMAN

Index

163

Index

A

Abstract Syntax Tree .......... 132 Achse..................................... 22 allgemeine Vergleiche .......... 72 and......................................... 69 arithmetische Operatoren...... 71 as ........................................... 98 ascending............................... 59 at ........................................... 51 Atomization......................... 102 attribute()............................... 90 avg......................................... 71

B

base-uri() ............................... 90 benutzerdefinierte

Fehlermeldung ................ 126 benutzerdefinierte

Funktionen ...................... 113 Boolean ................................. 82 BumbleBee.......................... 144 byte........................................ 87

C

cast as .................................... 99 castable as ............................. 99 Casting .................................. 59 ceiling.................................... 71 Character Information Items. 31 codepoints ........................... 112 code-points-to-string........... 110

collation ...............................113 collection()...........................104 comment()..............................90 compare ...............................110 concat...................................110 contains................................110 count()..................................105

D

data()..............................90, 102 date ........................................91 dateTime ................................91 Datums-Datentypen...............91 dayTimeDuration...................92 decimal ..................................87 Default-Namespace ...............98 descending .............................59 distinct-values................49, 107 div ..........................................71 doc().....................................104 document-node()....................90 Document-Type-Definition ...34 Dokumentenreihenfolge .60, 84,

107 double ....................................87 down-casting........................100 DTD.......................................34 duration..................................92 dynamischer Kontext...........134

Page 164: XQuery. Eine praxisorientierte Einführung  GERMAN

Index

164

E

EBV ...................................... 82 Effektive Boolean Value....... 82 element() ............................... 90 empty .................................. 107 empty greatest ....................... 60 empty least ............................ 60 ends-with............................. 110 ENTITY................................ 89 eq .......................................... 78 error() .................................. 126 escape-uri ............................ 110 every...................................... 55 exists ................................... 107 expanded-QName ................. 96 external ............................... 119 externe Funktionen ............. 119

F

Fehlerbehandlung ............... 125 float ....................................... 87 floor....................................... 71 FLWOR ................................ 44 for.......................................... 50

G

Galax................................... 141 ge .......................................... 78 get-hours-from-dateTime() ... 95 get-minutes-from-dateTime.. 95 Gruppierung........................ 108 gt .......................................... 78

I

ID...........................................89 idiv.........................................71 IDREF ...................................89 if-then-else.............................70 import ............................96, 121 index-of ...............................107 Inputfunktionen ...................103 insert-before ........................107 instance of ...........................100 int...........................................87 IPSI........................79, 132, 136

J

Java......................119, 127, 145 JDBC ...................................147 Joins.....................................122

K

Kawa....................................137 Knotentest..............................23 Konkatenation .......................67

L

language ................................89 le ...........................................78 left outer join .......................125 let ...........................................51 lexikografische Sortierung ....58 library module .....................120 local-name() ..........................90 Logische Operatoren .............69 Lokalisierungsschritt .............22 long........................................87

Page 165: XQuery. Eine praxisorientierte Einführung  GERMAN

Index

165

Lorel ...................................... 16 lower-case ........................... 110 lt ........................................... 78

M

main module........................ 120 matches ............................... 110 max........................................ 71 min ........................................ 71 mod ....................................... 71 Module ................................ 119

N

Name ..................................... 89 Namensraum ....................... 121 namespace() .......................... 90 namespace-uri()..................... 90 NaN ....................................... 83 NCName ............................... 89 ne ........................................... 78 negativeInteger...................... 87 NMTOKEN........................... 89 node-kind()............................ 90 node-name() .......................... 90 nonNegativeInteger............... 87 nonPositiveInteger ................ 87 normalizedString................... 89 not ......................................... 69 numerische Sortierung .......... 59

O

occurrence indicator.............. 86 or ........................................... 69 Oracle.................................. 136 order by ................................. 57

P

Parsing .................................132 Prädikat..................................23 processing-instruction().........90 Prolog ..................................119

Q

Qexo ....................137, 146, 155 Qizx .....................................142 QName...................................96 Query-Optimierung ...............10 Quilt .......................................16

R

Reihenfolge-Operatoren ........83 rekursive Funktionen...........118 replace..................................111 return......................................61 round......................................72 round-half-to-even.................72 Rückgabewert ........................61

S

Saxon ...........................135, 143 Sequenz..................................85

Funktionen.......................105 Servlets ................................155 short .......................................87 some.......................................54 SQL........................................16 SQL/XML......................16, 157 SQLJ ....................................148 starts-with ............................111 statischer Kontext ................132 string ......................................89

Page 166: XQuery. Eine praxisorientierte Einführung  GERMAN

Index

166

string()............................. 66, 90 string-join............................ 111 string-length........................ 111 String-Operationen ............. 109 string-to-codepoints ............ 111 string-value ........................... 91 Stylesheet .............................. 31 substring.............................. 111 sum........................................ 72 Systemfehlermeldung ......... 126

T

Tamino................................ 143 template................................. 31 text()...................................... 90 Textknoten ............................ 63 time ....................................... 92 token ..................................... 89 tokenize............................... 112 translate............................... 112 treat as ................................. 100 Tupel ..................................... 50 Typ-Casting .......................... 59 typed-value ..................... 58, 90 typeswitch ........................... 101 Typkonvertierung ................. 88 Typkonzept ........................... 85 Typoperatoren....................... 98 Typumwandlungen ............. 102

U

unordered ............................ 107 unsignedByte ........................ 87 unsignedInt ........................... 87 unsignedLong ....................... 87

unsignedShort........................87 untypedAtomic ......................96 update ..................................156 upper-case............................112

V

Vergleichs-Operatoren ..........72

W

W3C.......................................16 Wertevergleiche ..............72, 78 where .....................................53

X

XMLAgg ...............................16 XML-Dokumente

datenorientierte..................19 dokumentenorientierte.......19 hybride...............................20

XMLElement.........................16 XMLForest ............................16 XML-GL ...............................16 XML-QL ...............................16 XMLQuery ............................17 XML-Schema ........36, 117, 122 XPath .....................................22

Achse .................................22 Datentypen ........................29 Knotentest..........................23 Lokalisierungsschritt .........22 Prädikat..............................23

XQJ......................................147 XQL.......................................16 XQuery-Core-Language......132 XQuery-Engine .....................14

Page 167: XQuery. Eine praxisorientierte Einführung  GERMAN

Index

167

XSL ....................................... 16 XSLT..................................... 30

Stylesheet .......................... 31

Y

yearMonthDuration ...............92

Z

Zeit-Datentypen.....................91

Page 168: XQuery. Eine praxisorientierte Einführung  GERMAN