1 XQuery Informationssysteme, Vortragender: Michael Schmidt
2 XPath (Wiederholung) Anfragesprache auf XML XPath-Expressions selektieren Knoten des Eingabe-Dokuments bib book title author /bib//title
3 XPath (Wiederholung) Path Steps: axis::nodetest Axen: child, descendant, ancestor, following, following-sibling,... Node-tests: Tag, *, node(), text() Absolute Pfade: /step/step/… Relative Pfade: step/step/...
4 XQuery SQL für XML W3C Recommendation Funktionale Programmiersprache, Turing-vollständig XQueries enthalten XPath Ausdrücke Ergebnis einer XQuery: wohlgeformte XML- Dokumente (XPath: Menge von Knoten) Keine Datenmanipulationssprache (z.B. keine Updates)
5 Node-Construction und Konstanten { " Hello World " } XQuery Hello World Ergebnis " Hello World " XQuery "Hello World" Ergebnis
6 Dokument-Zugriff { doc( " bookstore.xml " )/bib/book[price>30] } T1 A1 50 T2 A2 20 T3 A3 bookstore.xml T1 A1 50 Ergebnis XQuery
7 Sequenz { ( doc( " bookstore.xml " )/bib/article/title, doc( " bookstore.xml " )/bib/book/title ) } T3 T1 T2 T1 A1 50 T2 A2 20 T3 A3 bookstore.xml Ergebnis XQuery Ordnung bleibt erhalten!
8 FR-Expression { for $book in doc( " bookstore.xml " )//book return $book/title } T1 A1 50 T2 A2 20 T3 A3 bookstore.xml T1 T2 Ergebnis XQuery
9 FWR-Expressions { for $book in doc( " bookstore.xml " )//book where $book/price>30 return { $book/title/text() } T1 A1 50 T2 A2 20 T3 A3 bookstore.xml T1 Ergebnis Konstruktion von Knoten, die im Dokument nicht vorkommen XQuery
10 FLWR-Expressions T1 A1 50 T2 A2 20 T3 A3 bookstore.xml { for $book in doc("bookstore.xml")//book let $booktitle := { $book/title/text() } where ($book/price>30) return $booktitle } T1 Ergebnis XQuery
11 FLWOR-Expressions { for $book in doc( " bookstore.xml " )//book let $booktitle := $book/title where ($book/price>10) order by $booktitle/text() descending return { $booktitle/text() } } T1 A1 50 T2 A2 20 T3 A3 bookstore.xml T2 T1 Ergebnis XQuery
12 Where-Expressions Konnektive and, or, fn:not T1 A1 50 T2 A2 20 T3 A3 bookstore.xml { for $book in doc( " bookstore.xml " )//book where ($book/price>10 and fn:not($book/author/text()= " A1 " )) return $book/title } T2 Ergebnis XQuery
13 Some-Expressions bookstore.xml { for $book in doc( " bookstore.xml " )//book where (some $a in $book/author satisfies $a/text()= " A2 " ) return $book/title } Ergebnis XQuery T1 A1 A2 T2 A3 A4 T1
14 For vs let-Expressions { for $x in (1 to 5) return {$x} } { let $x:=(1 to 5) return {$x} } XQuery 1 XQuery 2 Ergebnis Iteration keine Iteration Ergebnis
15 If-then-else Expressions { for $book in doc("bookstore.xml")//book return if (fn:exists($book/price)) then { $book/title } else { $book/title } } XQuery bookstore.xml T1 A1 T2 A2 30 T1 T2 Ergebnis
16 Vordefinierte Funktionen Zahlreiche built-in Functions: Boolean: fn:exists(), fn:empty() … String Manipulation: fn:concat(), fn:uppercase() … String Tests: fn:contains(), fn:starts-with() … Sequenzen: fn:exactly-one(), fn:distinct-values() … Mathematisch: fn:floor(), fn:round(), fn:abs() … …
17 Vordefinierte Funktionen { for $book in doc( " bookstore.xml " )//book where (fn:exists($book/price) and fn:contains($book/author, " A " )) return $book/title } XQuery T1 A1 50 T2 A2 20 T3 A3 bookstore.xml T1 T2 Ergebnis
18 XQuery Joins Vergleich unterschiedlicher Teile des Eingabe- Dokuments Auch Joins zwischen verschiedenen Dokumenten möglich Im Gegensatz zu SQL-Joins, oftmals nicht leicht zu erkennen, da keine eigene Syntax (kein JOIN-Keyword) Optimierung der Auswertung von Joins durch herkömmliche und XML-spezifische Methoden
19 XQuery Joins { for $bib in doc( " bookstore.xml " )/bib return for $book in $bib/book return for $article in $bib/article where $book/author=$article/author return { $book/title, $article/title} } XQuery bib book titleauthor T1A1 book titleauthor T2A2 article titleauthor T3A3 article titleauthor T4A1 $book $article T1 T4 Ergebnis
20 XQuery Joins { for $a in doc(" for $b in doc(" where $a/isbn = $b/isbn return { $b/title } { $a/price/text() } { $b/price/text() } } XQuery Join über zwei Dokumente
21 Aggregatfunktionen fn:min(), fn:max(), fn:count(), fn:sum(), fn:avg() { for $book in doc( " bookstore.xml " )//book return { ($book/title, { fn:count($book/author) } ) } XQuery bookstore.xml T1 A1 A2 T2 A3 T1 2 T2 1 Ergebnis
22 Aggregatfunktionen { for $o in fn:distinct-values(doc("adressen.xml")//ort) let $ort:=doc("adressen.xml")//ort[self::node()=$o] where fn:count($ort)>=2 order by $o return {($ort[1]/name,$ort[1]/plz)} {count($ort)} } Beispiel: Gegeben Adressdatenbank, berechne Orte und Zahl der Adressen für Orte mit mind. 2 Adressen adressen.xml SB S1 SB S2 … Ergebnis SB66121, NK66538, …
23 Datentransformation XML: Generalisierung von HTML XQuery ermöglicht Anfragen auf XML- Dokumente und direkte Ausgabe von HTML XML und XQuery in Web-Szenarien gut geeignet
24 Datentransformation T1 A1 50 T2 A2 20 T3 A3 bookstore.xml Angebot Buchliste { for $book in doc("bookstore.xml")//book return {$book/title/text()} {$book/author/text()} } XQuery
25 Datentransformation Angebot Buchliste T1 A1 T2 A2 Ergebnis
26 Vielfalt an Konstrukten FLWOR – Expressions Aggregationen Typkonversionen (nicht besprochen) Gleichheit von Knoten (Benutzerdefinierte) Funktionen Sehr komplex, effiziente Auswertung von XQuery noch immer ein aktives Forschungsgebiet
27 XQ – ein XQuery Fragment query ::= Ɛ | query | query query | var | var/axis::v | for var in var/axis::v return query | if cond then query else query cond ::= var = var | var = | true | some var in var/axis::v satisfies cond | cond and cond | cond or cond | not cond Syntax Composition-free XQ
28 Composition-free XQuery book bib book { let $x := { for $book in /bib/book return { $book } } for $b in $x/booklist/b return $b/* } XQuery
29 Composition-free XQuery book bib book booklist book b b $x $book { let $x := { for $book in /bib/book return { $book } } for $b in $x/booklist/b return $b/* } neu konstruiert XQuery
30 Composition-free XQuery book bib book booklist book b b $x book books book $book $b { let $x := { for $book in /bib/book return { $book } } for $b in $x/booklist/b return $b/* } XQuery
31 Composition-free XQuery in der Praxis: viele XQuery Anfragen mit Komposition können in äquivalente XQ-Anfragen umgeschrieben werden { let $x := { for $book in /bib/book return { $book } } for $b in $x/booklist/b return $b/* } { for $book in /bib/book return $book } XQuery XQ query
32 Eigenschaft von XQ niedrigere Komplexität in der Auswertung Variablen binden immer an einen Knoten im Eingabebaum { for $x in //x return for $y in $x//y return $y } x x yy $x r Ergebnis XQ expression
33 Eigenschaft von XQ niedrigere Komplexität in der Auswertung Variablen binden immer an einen Knoten im Eingabebaum x x yy $x $y r Ergebnis { for $x in //x return for $y in $x//y return $y } XQ expression
34 Eigenschaft von XQ niedrigere Komplexität in der Auswertung Variablen binden immer an einen Knoten im Eingabebaum x x yy $x $y r Ergebnis { for $x in //x return for $y in $x//y return $y } XQ expression
35 Eigenschaft von XQ niedrigere Komplexität in der Auswertung Variablen binden immer an einen Knoten im Eingabebaum x x yy $x r Ergebnis { for $x in //x return for $y in $x//y return $y } XQ expression
36 Eigenschaft von XQ niedrigere Komplexität in der Auswertung Variablen binden immer an einen Knoten im Eingabebaum x x yy $y r $x Ergebnis { for $x in //x return for $y in $x//y return $y } XQ expression
37 Eigenschaft von XQ niedrigere Komplexität in der Auswertung Variablen binden immer an einen Knoten im Eingabebaum x x yy r $x $y Ergebnis { for $x in //x return for $y in $x//y return $y } XQ expression
38 XQ formale Semantik k: Anzahl gebundener Variablen e: derzeitiges environment (Variablenbindung) false als leere Liste Ergebnis: Liste von Knoten
39 XQ formale Semantik
40 XQ formale Semantik
41 XQ Evaluierung [[ { $x 2 $x 1 } ]] 2 (, ) = [ [[$x 2 $x 1 ]] 2 (, ) ] = [ [[$x 2 ]] 2 (, ) [[$x 1 ]] 2 (, ) ] = [ ]
42 XQ Evaluierung { for $book in //book return if (some $author in $book/author satisfies $author/text()=A1) then $book else () } bookstore.xml T1 A1 T2 A2 XQuery
43 XQ Evaluierung [[ { for $book in //book return if (some $author in $book/author satisfies $author/text()=A1) then $book else ()} ]] 0 ()
44 XQ Evaluierung [[ { for $book in //book return if (some $author in $book/author satisfies $author/text()=A1) then $book else ()} ]] 0 () [[for $book in //book return if (some $author in $book/author satisfies $author/text()=A1) then $book else ()]] 0 ()
45 XQ Evaluierung [[ { for $book in //book return if (some $author in $book/author satisfies $author/text()=A1) then $book else ()} ]] 0 () [[for $book in //book return if (some $author in $book/author satisfies $author/text()=A1) then $book else ()]] 0 () l=[[//book]] 0 () = [ A1 T1, A2 T2 ]
46 XQ Evaluierung [[ { for $book in //book return if (some $author in $book/author satisfies $author/text()=A1) then $book else ()} ]] 0 () [[for $book in //book return if (some $author in $book/author satisfies $author/text()=A1) then $book else ()]] 0 () l=[[//book]] 0 () = [ A1 T1, A2 T2 ] [[if (some …)]] 1 (l 1 ) + [[if (some …)]] 1 (l 2 )
47 XQ Evaluierung [[if (some $author in $book/author satisfies $author/text()=A1) then $book else ()]] 1 ( A1 T1 ) [[ { for $book in //book return if (some $author in $book/author satisfies $author/text()=A1) then $book else ()} ]] 0 () [[for $book in //book return if (some $author in $book/author satisfies $author/text()=A1) then $book else ()]] 0 () l=[[//book]] 0 () = [ A1 T1, A2 T2 ] [[if (some …)]] 1 (l 1 ) + [[if (some …)]] 1 (l 2 )
48 XQ Evaluierung [[for $author in $book/author return $author/text()=A1]] 1 ( A1 T1 ) [[if (some $author in $book/author satisfies $author/text()=A1) then $book else ()]] 1 ( A1 T1 ) [[ { for $book in //book return if (some $author in $book/author satisfies $author/text()=A1) then $book else ()} ]] 0 () [[for $book in //book return if (some $author in $book/author satisfies $author/text()=A1) then $book else ()]] 0 () l=[[//book]] 0 () = [ A1 T1, A2 T2 ] [[if (some …)]] 1 (l 1 ) + [[if (some …)]] 1 (l 2 )
49 XQ Evaluierung l =[[$book/author]] 1 ( A1 T1 ) = [ A1 ] [[for $author in $book/author return $author/text()=A1]] 1 ( A1 T1 ) [[ { for $book in //book return if (some $author in $book/author satisfies $author/text()=A1) then $book else ()} ]] 0 () [[for $book in //book return if (some $author in $book/author satisfies $author/text()=A1) then $book else ()]] 0 () l=[[//book]] 0 () = [ A1 T1, A2 T2 ] [[if (some …)]] 1 (l 2 ) + [[if (some …)]] 1 (l 1 ) [[if (some $author in $book/author satisfies $author/text()=A1) then $book else ()]] 1 ( A1 T1 ) [[$author/text()=A1]] 2 ( …, A1 )
50 XQ Evaluierung [[$author/text()=A1]] 2 ( …, A1 ) [ ] l =[[$book/author]] 1 ( A1 T1 ) = [ A1 ] [[for $author in $book/author return $author/text()=A1]] 1 ( A1 T1 ) [[if (some $author in $book/author satisfies $author/text()=A1) then $book else ()]] 1 ( A1 T1 ) [[ { for $book in //book return if (some $author in $book/author satisfies $author/text()=A1) then $book else ()} ]] 0 () [[for $book in //book return if (some $author in $book/author satisfies $author/text()=A1) then $book else ()]] 0 () l=[[//book]] 0 () = [ A1 T1, A2 T2 ] [[if (some …)]] 1 (l 1 ) + [[if (some …)]] 1 (l 2 ) [[$author/text()]] 2 (…) [A1] [[A1]] 2 (…) [A1]
51 XQ Evaluierung [[$author/text()=A1]] 2 ( …, A1 ) [ ] l =[[$book/author]] 1 ( A1 T1 ) = [ A1 ] [[for $author in $book/author return $author/text()=A1]] 1 ( A1 T1 ) [ ] [[if (some $author in $book/author satisfies $author/text()=A1) then $book else ()]] 1 ( A1 T1 ) [[ { for $book in //book return if (some $author in $book/author satisfies $author/text()=A1) then $book else ()} ]] 0 () [[for $book in //book return if (some $author in $book/author satisfies $author/text()=A1) then $book else ()]] 0 () l=[[//book]] 0 () = [ A1 T1, A2 T2 ] [[if (some …)]] 1 (l 1 ) + [[if (some …)]] 1 (l 2 )
52 XQ Evaluierung [[$book]] 1 ( A1 T1 ) [ A1 T1 ] [[$author/text()=A1]] 2 ( …, A1 ) [ ] l =[[$book/author]] 1 ( A1 T1 ) = [ A1 ] [[for $author in $book/author return $author/text()=A1]] 1 ( A1 T1 ) [ ] [[if (some $author in $book/author satisfies $author/text()=A1) then $book else ()]] 1 ( A1 T1 ) [ A1 T1 ] [[ { for $book in //book return if (some $author in $book/author satisfies $author/text()=A1) then $book else ()} ]] 0 () [[for $book in //book return if (some $author in $book/author satisfies $author/text()=A1) then $book else ()]] 0 () l=[[//book]] 0 () = [ A1 T1, A2 T2 ] [[if (some …)]] 1 (l 1 ) + [[if (some …)]] 1 (l 2 ) [ A1 T1 ] +
53 XQ Evaluierung [[ { for $book in //book return if (some $author in $book/author satisfies $author/text()=A1) then $book else ()} ]] 0 () [[for $book in //book return if (some $author in $book/author satisfies $author/text()=A1) then $book else ()]] 0 () l=[[//book]] 0 () = [ A1 T1, A2 T2 ] [[if (some …)]] 1 (l 1 ) + [[if (some …)]] 1 (l 2 ) [ A1 T1 ] + [[if (some $author in $book/author satisfies $author/text()=A1) then $book else ()]] 1 ( A2 T2 )
54 XQ Evaluierung [[ { for $book in //book return if (some $author in $book/author satisfies $author/text()=A1) then $book else ()} ]] 0 () [[for $book in //book return if (some $author in $book/author satisfies $author/text()=A1) then $book else ()]] 0 () l=[[//book]] 0 ()= [ A1 T1, A2 T2 ] [[if (some …)]] 1 (l 0 ) + [[if (some …)]] 1 (l 1 ) [ A1 T1 ] + [[if (some $author in $book/author satisfies $author/text()=A1) then $book else ()]] 1 ( A2 T2 ) [[for $author in $book/author return $author/text()=A1]] 1 ( A2 T2 )
55 XQ Evaluierung [[ { for $book in //book return if (some $author in $book/author satisfies $author/text()=A1) then $book else ()} ]] 0 () [[for $book in //book return if (some $author in $book/author satisfies $author/text()=A1) then $book else ()]] 0 () l=[[//book]] 0 ()= [ A1 T1, A2 T2 ] [[if (some …)]] 1 (l 1 ) + [[if (some …)]] 1 (l 2 ) [ A1 T1 ] + [[if (some $author in $book/author satisfies $author/text()=A1) then $book else ()]] 1 ( A2 T2 ) [[for $author in $book/author return $author/text()=A1]] 1 ( A2 T2 ) l =[[$book/author]] 1 ( A2 T2 ) = [ A2 ] [[$author/text()=A1]] 2 ( …, A2 )
56 XQ Evaluierung [[ { for $book in //book return if (some $author in $book/author satisfies $author/text()=A1) then $book else ()} ]] 0 () [[for $book in //book return if (some $author in $book/author satisfies $author/text()=A1) then $book else ()]] 0 () l=[[//book]] 0 () = [ A1 T1, A2 T2 ] [[if (some …)]] 1 (l 1 ) + [[if (some …)]] 1 (l 2 ) [ A1 T1 ] + [[if (some $author in $book/author satisfies $author/text()=A1) then $book else ()]] 1 ( A2 T2 ) [[for $author in $book/author return $author/text()=A1]] 1 ( A2 T2 ) l =[[$book/author]] 1 ( A2 T2 ) = [ A2 ] [[$author/text()=A1]] 2 ( …, A2 ) [] [[$author/text()]] 2 (…) [A2] [[A1]] 2 (…) [A1]
57 XQ Evaluierung [[ { for $book in //book return if (some $author in $book/author satisfies $author/text()=A1) then $book else ()} ]] 0 () [[for $book in //book return if (some $author in $book/author satisfies $author/text()=A1) then $book else ()]] 0 () l=[[//book]] 0 () = [ A1 T1, A2 T2 ] [[if (some …)]] 1 (l 1 ) + [[if (some …)]] 1 (l 2 ) [ A1 T1 ] + [[if (some $author in $book/author satisfies $author/text()=A1) then $book else ()]] 1 ( A2 T2 ) [[for $author in $book/author return $author/text()=A1]] 1 ( A2 T2 ) [] l =[[$book/author]] 1 ( A2 T2 ) = [ A2 ] [[$author/text()=A1]] 2 ( …, A2 ) []
58 XQ Evaluierung [[ { for $book in //book return if (some $author in $book/author satisfies $author/text()=A1) then $book else ()} ]] 0 () [[for $book in //book return if (some $author in $book/author satisfies $author/text()=A1) then $book else ()]] 0 () l=[[//book]] 0 () = [ A1 T1, A2 T2 ] [[if (some …)]] 1 (l 1 ) + [[if (some …)]] 1 (l 2 ) [ A1 T1 ] + [[if (some $author in $book/author satisfies $author/text()=A1) then $book else ()]] 1 ( A2 T2 ) [] [[for $author in $book/author return $author/text()=A1]] 1 ( A2 T2 ) [] l =[[$book/author]] 1 ( A2 T2 ) = [ A2 ] [[$author/text()=A1]] 2 ( …, A2 ) [] [[()]] 1 ( A2 T2 ) [] []
59 XQ Evaluierung [[ { for $book in //book return if (some $author in $book/author satisfies $author/text()=A1) then $book else ()} ]] 0 () [[for $book in //book return if (some $author in $book/author satisfies $author/text()=A1) then $book else ()]] 0 () [ A1 T1 ] l=[[//book]] 0 () = [ A1 T1, A2 T2 ] [[if (some …)]] 1 (l 1 ) + [[if (some …)]] 1 (l 2 ) [ A1 T1 ] + [] [[if (some $author in $book/author satisfies $author/text()=A1) then $book else ()]] 1 ( A2 T2 ) [] [[for $author in $book/author return $author/text()=A1]] 1 ( A2 T2 ) [] l =[[$book/author]] 1 ( A2 T2 ) = [ A2 ] [[$author/text()=A1]] 2 ( …, A2 ) [] [[()]] 1 ( A2 T2 ) []
60 XQ Evaluierung [[ { for $book in //book return if (some $author in $book/author satisfies $author/text()=A1) then $book else ()} ]] 0 () [ A1 T1 ] [[for $book in //book return if (some $author in $book/author satisfies $author/text()=A1) then $book else ()]] 0 () [ A1 T1 ] l=[[//book]] 0 () = [ A1 T1, A2 T2 ] [[if (some …)]] 1 (l 1 ) + [[if (some …)]] 1 (l 2 ) [ A1 T1 ] + [] [[if (some $author in $book/author satisfies $author/text()=A1) then $book else ()]] 1 ( A2 T2 ) [] [[for $author in $book/author return $author/text()=A1]] 1 ( A2 T2 ) [] l =[[$book/author]] 1 ( A2 T2 ) = [ A2 ] [[$author/text()=A1]] 2 ( …, A2 ) [] [[()]] 1 ( A2 T2 ) []
61 XQ: 2 Arten von Gleichheit Deep Equality Vergleiche Bäume als Werte z.B.: n1 deep-equal n2 n2 deep-equal n7 n3 = deep-equal n10 n4 = deep-equal n11 n4 deep-equal n10 Atomic Equality Vergleiche Blätter als Werte z.B.: n4 = atomic n11 n4 atomic n9 n1: people n2: person n4: Karln6: Auer n7: person n5: lnn3: fn n9: Auern11: Karl n10: fnn8: ln
62 XQuery – Komplexere Beispiele { for $b in doc("doc.xml")//book where fn:count($b/author) > 0 return { $b/title } { for $a in $b/author[position()<=2] return $a } { if (fn:count($b/author) > 2) then else () } } Für jedes Buch mit mindestens einem Autor, gib den Titel und die ersten beiden Autoren aus und ein leeres et-al-Element wenn das Buch weitere Autoren besitzt XQuery
63 XQuery – Komplexere Beispiele Finde den minimalen Preis für jedes Buch und gib ihn in der Form eines minprice-Elements mit dem Titel des Buchs als title-Attribut aus. { let $doc := doc("doc.xml") for $t in fn:distinct-values($doc//book/title) let $p := $doc//book[title = $t]/price return { fn:min($p) } } XQuery
64 XQuery – Komplexere Beispiele Gib alle Paare von Büchern aus, die unterschiedliche Titel aber die selben Autoren (möglicherweise in unterschiedlicher Reihenfolge) haben. { for $book1 in doc("doc.xml")//book, $book2 in doc("doc.xml")//book let $aut1:=for $a in $book1/author order by $a/last, $a/first return $a let $aut2 := for $a in $book2/author order by $a/last, $a/first return $a where $book1 << $book2 and not($book1/title = $book2/title) and fn:deep-equal($aut1, $aut2) return { $book1/title } { $book2/title } } XQuery Annahme: Autoren haben die Form FIRSTNAME LASTNAME <<: vor
65 Literatur und Links Buch XQuery from the Experts, Addison Wesley (Kapitel 1) (Howard Katz, Don Chamberlin, Denise Draper, Mary Fernandez, Michael Kay, Jonathan Robie, Michael Rys, Jerome Simeon, Jim Tivy, Philip Wadler) XQuery Tutorial: W3C XQuery: W3C XQuery Functions: Galax XQuery Engine (installiert in CIP-Pools):