Einführung in die XML-Technologien XPath, XSLT und XQuery/XQuery
Aus ProgrammingWiki
Wiki-Quelltext dieser Seite.
<language>XQuery</language>
Autoren
* Fred Teske([mailto:s3frtesk@stud.hs-zigr.de s3frtesk@stud.hs-zigr.de ])
* Philipp Dvorak ([mailto:s3phdvor@stud.hs-zigr.de s3phdvor@stud.hs-zigr.de])
=Einstieg in XQuery=
XQuery ist ein Abfragesprache für XML. Welche ein Empfehlung vom W3C ist. In diesem Kurs sollen die grundlegenden Spracheigenschaften vorgestellt werden und ein Verständnis der Syntax und Struktur von XQuery – Ausdrücken vermittelt werden.
XQuery ermöglicht:
* das Auswählen von Elementen und Attributen
* das Zusammenführen mehrerer XML-Dokumente
* das Bearbeiten von XML-Daten
* das Hinzufügen von Elementen und Attributen zu der Ergebnismengen
* Berechnungen auf Grundlage von XML-Daten
* Sortierungen der Ergebnismenge
=Datenmodell=
Die Basis des XQuery Datenmodells sind Sequenzen. Eine Sequenz ist die Sammlung einzelner sogenannter Items, welche mit einem Komma voneinander getrennt sind. Es sind Duplikate von Items möglich. Sie funktioniert nach dem fifo – Prinzip (first in first out) d.h. Das Item, das als erstes in die Sequenz eingestellt wurde, wird auch als erstes wieder ausgegeben. Die einzelnen Items können unterschiedliche Datentypen haben. XQuery bestitz eigene Datentypen für atomare Wert und von XML Schema geerbte Datentypen.
[[Bild:XQueryDatentypen.png|450px]]
'''Beispiele für Sequenzen'''
*atomare Ganzzahl
2
*atomare Zeichenkette
'hallo'
*drei atomare Wert
(1, 2, 3)
*XML Elementknoten
<schauspieler/>
*atomare Werte und XML Elementknoten
(1, <schauspieler/>, 'hallo')
*leere Sequenz
()
Die Empfehlungen vom W3C für XQuery und XPath überschneiden sich. XPath bildet eine Untermenge von XQuery. Somit ist jeder gültige XPath - Ausdruck auch ein gültiger XQuery - Ausdruck. XQuery ist selbst keine XML - Anwendung. XQuery bestitz eine eigene Syntax.
[[Bild:XQuery.jpg|450px]]
=Syntax=
Bei XQuery handelt es sich um eine funktionale Sprache. Eine Abfrage wird als Ausdruck formuliert, der anschließend ausgewertet wird. Ausdrücke können beliebig verschachtelt werden. Schlüsselworter werden kleingeschrieben und sind bis auf wenige Ausnahmen nicht reserviert.
Die Abfragen werden aus mehreren Modulen zusammengestellt. Das Hauptmodul besteht aus einem optionalen Prolog und dem Teil in dem die eigentliche Abfrage formuliert wird der Query Body. Des Weiteren sind Bibliotheksmodule für beispielsweise benutzerdefinierte Funktionen möglich.
Der Prolog gliedert sich in zwei Teile. Im ersten Teil ist es möglich Einstellungen zu machen, welche die Verarbeitung durch den XQuery-Prozessor beeinflussen. Der zweite Teil ist für die Deklaration von Variablen und dem Import von Funktionen und Optionen vorgesehen.
Folgende XML-Dokumente sollen als Basis für Beispiele und Erläuterungen dienen.
<popup name = "Beispieldokument filmliste.xml">
<code id="4ef9e82aad7a8">
<filmliste>
<film id="1">
<titel>Die Rueckkehr der Jedi-Ritter</titel>
<genre>Science-Fiction</genre>
<oscars>1</oscars>
<regie>
<regisseur>Richard</regisseur>
</regie>
<jahr>1983</jahr>
</film>
<film id="2">
<titel>Sin City</titel>
<genre>Thriller</genre>
<oscars>0</oscars>
<regie>
<regisseur>Frank Miller</regisseur>
<regisseur>Robert Rodriguez</regisseur>
<regisseur>Quentin Tarantino</regisseur>
</regie>
<jahr>2005</jahr>
</film>
<film id="3">
<titel>Forrest Gump</titel>
<genre>Drama</genre>
<oscars>6</oscars>
<regie>
<regisseur>Robert Zemeckis</regisseur>
</regie>
<jahr>1994</jahr>
</film>
<film id="4">
<titel>The Dark Knight</titel>
<genre>Action</genre>
<oscars>2</oscars>
<regie>
<regisseur>Christopher Nolan</regisseur>
</regie>
<jahr>2008</jahr>
</film>
<film id="5">
<titel>Avatar</titel>
<genre>Science-Fiction</genre>
<oscars>3</oscars>
<regie>
<regisseur>James Cameron</regisseur>
</regie>
<jahr>2009</jahr>
</film>
</filmliste>
</code>
</popup>
=Arithmetik=
=FLWOR - Ausdrücke=
FLWOR - Ausdrücke bilden die Grundlage für Anfragen an XML - Dokumente. Der Ausdruck bindet Variablen an Ergebnisse von Ausdrücken, wertet darauf in einer where-Klausel ein Prädikat aus und konstruiert ein neues Dokument als Resultat. FLWOR - Ausdrücke weisen Ähnlichkeiten mit Abfragen im SQL - Syntax auf. FLWOR ist ein Kunstwort (aus dem englischen "Flower"). Die einzelnen Buchstaben entsprechen dabei den Anfangsbuchstaben der Klauseln des Ausdrucks: for, let, where, order und return.
Ein einfacher FLWOR - Ausdruck ist zum Beispiel folgendes:
<run id="4ef330571dd87">
for $v in //filmliste/film
return $v/titel
</run>
Dieser Ausdruck gibt alle Filmtitel aus dem Beispiel XML-Dokument "filmliste" zurückgeben.
Mit einer zusätzlichen where Klausel kann die Ergebnismenge weiter eingegrenzt werden.
<run id="4ef330571ddf5">
for $v in //filmliste/film
where $v/jahr = 2009
return $v/titel
</run>
Die gleiche Abfrage könnte auch mit Hilfe des XPath - Ausdrucks:
/filmliste/film[jahr=2009]/titel
ausgeführt werden. Der XPath - Ausdruck liefert genau die selbe Ergebnismenge wie der XQuery - Ausdruck. Es gilt jeder gültige XPath - Ausdruck ist auch in XQuery zulässig. Jedoch sind FLWOR - Ausdrücke in XQuery weitaus leistungsfähiger wenn es darum geht mit Hilfe von JOINS Abfragen über mehrere XML-Dokumente auszuführen.
<language>XQuery</language>
<language>XQuery</language>
==Die for-Klausel==
In der for-Klausel wird über eine Sequenz iteriert. Es handelt sich entweder um eine Sequenz von Knoten oder um eine Sequenz aus atomaren Werten. Es kann eine beliebige Operation auf alle Elemente der Sequenz angewendet werden.
<run id="4ef344c255b35">
for $i in (1 to 10)
return $i * $i
</run>
Bei $i handelt es sich um die Iterationsvariable, welche jeden Wert der Sequenz einmal annimmt. Es ist mehr als eine for-Klausel pro Ausdruck möglich.
Ein FLWOR - Ausdruck kann an jeder beliebigen stelle stehen an der ein Ausdruck erlaubt ist. Beispielsweise kann ein FLWOR - Ausdruck als Argument an eine Funktion übergeben werden.
Die Funktion avg() berechnet den Durchschnitt aus der Sequenz, welche der FLWOR - Ausdruck zurückgibt. Im Beispiel wird die durchschnittliche Anzahl der Regisseure ermittelt, die an einem Film gearbeitet haben.
<run id="4f05a6b7ab2b4">
avg(
for $film in //filmliste/film
return count($film/regie/regisseur)
)
</run>
==Die let-Klausel==
Mit Hilfe der Let-Klausel ist es möglich Variablen zu deklarieren. Im Gegensatz zur for – Klausel, in der die Listenelemente durchlaufen werden, ist in der let – Klausel die Variable immer an das Element gebunden. Das kann ein atomarer Wert sein oder eine Sequenz. Der Wert der Variablen, welche mit let deklariert wurde, wird in jedem Schleifendurchlauf neu belegt.
<run id="4ef385fdaa212">
for $i in (1, 2, 3)
let $j := (1, 2, 3)
return
<eval><i>{ $i }</i><j>{ $j }</j></eval>
</run>
==Die where-Klausel==
Die where – Klausel wird dazu verwendet die gesuchten Elemente aus einer Sequenz zu filtern. Es wird anhand eines Prädikats entschieden ob das Element in die Ergebnismenge aufgenommen werden soll oder nicht. In der where – Klausel können sich weitere Ausdrücke befinden. Die Verwendung einer where-Klausel in einem XQuery – Ausdruck ist optional. Wenn sie aber verwendet wird, dann darf es nur eine where-Klausel nach den for- und let - Klauseln im entsprechenden XQuery – Ausdruck geben. Das where in XQuery ist vergleichbar mit dem where in SQL.
<run id="4ef474f5063f0">
for $i in /filmliste/film
where $i/oscars = 6
return $i/titel
</run>
==Die order by - Klausel==
Mit der order by – Klausel ist eine Sortierung der Ergebnismenge möglich. Mit dem Schlüsselwort ascending lässt sich die Ergebnismenge aufsteigend sortieren bzw. mit descending absteigend. Die Klausel ist genau wie die where Klausel optional. Ohne order by werden die Elemente in der Ergebnissequenz in der Reihenfolge ausgegeben wie sie im abgefragten XML-Dokumente auftreten.
<run id="4ef47d73b6560">
for $i in /filmliste/film
where $i/oscars >= 1
order by $i/jahr descending
return $i/titel
</run>
==Die return Klausel==
Jeder FLWOR – Ausdruck hat eine return – Klausel. Mit ihrer hilfe wird das Ergebnis konstruiert. Im return Teil können Konstruktoren zum Einsatz kommen. Für jeden Knotentyp gibt es einen Konstruktor, der eine Instanz vom jeweiligen Knotentyp erzeugt. Zum Beispiel einen Elementknoten.
<run id="4ef4823cb4f18">
for $i in /filmliste/film
where $i/oscars >= 1
order by $i/jahr descending
return element erfolge{$i/titel}
</run>
Unter unten stehendem Link finden Sie Übungsaufgaben zu den FLWOR - Ausdrücken, die Ihnen helfen sollen den Umgang mit den in XQuery häufig vorkommenden Ausdrücken etwas einzuüben.
*[[Einführung_in_die_XML-Technologien_XPath,_XSLT_und_XQuery/XQuery/Übungen_FLWOR_-_Ausdrücke|Übungsaufgaben]]
=Joins=
Mit Hilfe von Joins können mehrere Eingabedokumente zu einer Ergebnismenge zusammengeführt werden. In XQuery geschieht dies mit geschachtelten FLWOR Ausdrücken.
Für das Beispiel wird ein weiteres XML - Dokument verwendet.
<popup name="Beispieldokument schauspielerliste.xml">
<schauspielerliste>
<schauspieler>
<name>Ford</name>
<vorname>Harrison</vorname>
<filmid>1</filmid>
</schauspieler>
<schauspieler>
<name>Hamill</name>
<vorname>Mark</vorname>
<filmid>1</filmid>
</schauspieler>
<schauspieler>
<name>Alba</name>
<vorname>Jessica</vorname>
<filmid>2</filmid>
</schauspieler>
<schauspieler>
<name>Dawson</name>
<vorname>Rosario </vorname>
<filmid>2</filmid>
</schauspieler>
<schauspieler>
<name>Wood</name>
<vorname>Elijah </vorname>
<filmid>2</filmid>
</schauspieler>
<schauspieler>
<name>Willis</name>
<vorname>Bruce </vorname>
<filmid>2</filmid>
</schauspieler>
<schauspieler>
<name>Hanks</name>
<vorname>Tom </vorname>
<filmid>3</filmid>
</schauspieler>
<schauspieler>
<name>Bale</name>
<vorname>Christian </vorname>
<filmid>4</filmid>
</schauspieler>
<schauspieler>
<name>Ledger</name>
<vorname>Heath </vorname>
<filmid>4</filmid>
</schauspieler>
<schauspieler>
<name>Eckhart</name>
<vorname>Aaron </vorname>
<filmid>4</filmid>
</schauspieler>
<schauspieler>
<name>Worthington</name>
<vorname>Sam</vorname>
<filmid>5</filmid>
</schauspieler>
<schauspieler>
<name>Saldana</name>
<vorname>Zoe</vorname>
<filmid>5</filmid>
</schauspieler>
</schauspielerliste>
</popup>
Es sollen die Schauspieler ermittelt werden, welche im Film "Sin City" mitgespielt haben.
for $filme in //filmliste/film
where $filme/titel = "Sin City"
return <besetzung>{
(
for $schauspieler in //schauspielerliste/schauspieler
where $schauspieler/filmid = $filme/@id
return <schauspieler>{($schauspieler/vorname, $schauspieler/name)}</schauspieler>
)
}</besetzung>
Die Ergebnismenge der obigen Anfrage:
<besetzung>
<schauspieler>
<vorname>Jessica</vorname>
<name>Alba</name>
</schauspieler>
<schauspieler>
<vorname>Rosario </vorname>
<name>Dawson</name>
</schauspieler>
<schauspieler>
<vorname>Elijah </vorname>
<nam>Wood</name>
</schauspieler>
<schauspieler>
<vorname>Bruce </vorname>
<name>Willis</name>
</schauspieler>
</besetzung>
=Vordefinierte Funktionen=
In XQuery gibt es mehr als 100 vordefinierte Funktionen, die die Datenabfrage aus XML-Dokumenten unterstützen. Beispielsweise die ''data'' Funktion. Mit ihrer Hilfe kann der Wert eines Knotens zurückgegeben jedoch nicht der komplette Knoten mit Start- und Endtag.
<run id="4f05a5e721037">
for $film in /filmliste/film
where $film/@id = 4
return data($film/titel)
</run>
Unter anderem gibt es Funktionen für die Arbeit mit Strings, Datumsangaben, Knoten, Sequenzen und boolschen Werten.
Eine Übersicht über vordefinierte XQuery Funktionen findet sich hier.
http://www.xqueryfunctions.com/
=Benutzerdefinierte Funktionen=
XQuery bietet die Möglichkeit Funktionen selbst zu deklarieren. Eine benutzerdefinierte Funktionen beginnt mit ''declare function'' gefolgt von einem Präfix ''extern'' oder ''local''. Lokale Funktionen innerhalb eines Hauptmoduls werden mit dem Präfix ''local'' definiert. Local ist an den Namensraum http://www.w3.org/2005/xquery-local-functions gebunden. Des Weiteren besteht die Funktion aus einem Funktionskopf, welcher den Namen der Funktion enthält. Sowie die an die Funktion übergebenen Argumente und dem Datentyp des Rückgabewertes. Den Funktionsrumpf bildet ein Xquery-Ausdruck.
Benutzerdefinierte Funktionen können auch rekursiv definiert werden.
<run id="4f02fc9cb1987">
declare function local:fak( $n as xs:integer ) as xs:integer {
if ($n = 0)
then 1
else $n * local:fak($n - 1)
};
<fakultaet>Fakultät von 5 ist { local:fak(5) }</fakultaet>
</run>
*[[Einführung_in_die_XML-Technologien_XPath,_XSLT_und_XQuery/XQuery/Übungen_benutzerdefinierte_Funktionen|Übungsaufgaben]]
=If-Then-Else Anweisungen=
XQuery unterstütz If-Then-Else Anweisungen. Dabei wird wie auch in anderen Sprachen üblich in Abhängigkeit eines boolschen Wertes, entweder der then-Ausdruck oder der else-Ausdruck einer If-Then-Else Anweisung ausgewertet. Der zu testende Ausdruck muss in Klammern stehen. Das else muss in XQuery immer enthalten sein. Wenn es nicht benötigt wird kann auch () (leere Sequenz) zurückgegeben werden. Es ist möglich mehrere If-Then-Else – Anweisungen zu schachteln.
<run id="4f02f9c47702b">
for $film in /filmliste/film
return if ($film/oscars > 0)
then <auszeichnungen>{data($film/titel) , " wurde mit", sum($film/oscars) , if($film/oscars = 1) then( "Oscar") else( "Oscars"), " ausgezeichnet"}</auszeichnungen>
else <auszeichnungen>{data( $film/titel), "hat keine Auszeichnungen erhalten"}</auszeichnungen>
</run>