XQuery Przykład – dokument XML XQuery – wyrażenie ścieżkowe
Transkrypt
XQuery Przykład – dokument XML XQuery – wyrażenie ścieżkowe
XQuery ¾XQuery (XML Query Language) XQuery 1.0: An XML Query Language. W3C Recommendation XQuery http://www.w3.org/TR/xquery/ ¾Język programowania funkcyjnego (podobnie jak Lisp) ¾Język zapytań do danych XML-owych Tadeusz Pankowski www.put.poznan.pl/~tadeusz.pankowski T. Pankowski Przykład – dokument XML XQuery – wyrażenie ścieżkowe <bib> <ksiazka cena="55.00"> <tytul>XML</tytul> <autor>Nowak</autor> <autor>Kubiak</autor> <wydawnictwo> PWN </wydawnictwo> </ksiazka> <ksiazka cena="70.00"> <tytul>SQL</tytul> <autor>Nowak</autor> <autor>Kubiak</autor> <autor>Lipski</autor> <wydawnictwo> PWN </wydawnictwo> </ksiazka> </bib> <bib> <ksiazka cena="55.00"> <tytul>XML</tytul> <autor>Nowak</autor> <autor>Kubiak</autor> <wydawnictwo>PWN</wydawnictwo> </ksiazka> <ksiazka cena="70.00"> <tytul>SQL</tytul> <autor>Nowak</autor> <autor>Kubiak</autor> <autor>Lipski</autor> <wydawnictwo>PWN</wydawnictwo> </ksiazka> </bib> T. Pankowski 2 3 Podaj autorów książek w cenie mniejszej niż 60 zł Wyrażenie ścieżkowe: doc("bib.xml")/bib/ksiazka[@cena<60]/autor SQL Server: select bib.query('/bib/ksiazka[@cena<60]/autor') from bib Wynik: <autor>Nowak</autor> <autor>Kubiak</autor> Wynik nie jest dokumentem XML. Jest sekwencją dwóch fragmentów. T. Pankowski ! 4 XQuery – wyrażenie FLWOR <bib> <ksiazka cena="55.00"> <tytul>XML</tytul> <autor>Nowak</autor> <autor>Kubiak</autor> <wydawnictwo> PWN </wydawnictwo> </ksiazka> <ksiazka cena="70.00"> <tytul>SQL</tytul> <autor>Nowak</autor> <autor>Kubiak</autor> <autor>Lipski</autor> <wydawnictwo> PWN </wydawnictwo> </ksiazka> </bib> XQuery – konstruowanie dokumentu Podaj autorów książek w cenie mniejszej niż 60 zł <bib> <ksiazka cena="55.00"> <tytul>XML</tytul> <autor>Nowak</autor> <autor>Kubiak</autor> <wydawnictwo> PWN </wydawnictwo> </ksiazka> <ksiazka cena="70.00"> <tytul>SQL</tytul> <autor>Nowak</autor> <autor>Kubiak</autor> <autor>Lipski</autor> <wydawnictwo> PWN </wydawnictwo> </ksiazka> </bib> Wyrażenie FLWOR: for $k in doc("bib.xml")/bib/ksiazka where $k/@cena<60 return $k/autor SQL Server: select bib.query(' for $k in /bib/ksiazka where $k/@cena<60 return $k/autor') from bib Wynik: <autor>Nowak</autor> <autor>Kubiak</autor> T. Pankowski 5 XQuery – konstruowanie dokumentu <bib> <ksiazka cena="55.00"> <tytul>XML</tytul> <autor>Nowak</autor> <autor>Kubiak</autor> <wydawnictwo> PWN </wydawnictwo> </ksiazka> <ksiazka cena="70.00"> <tytul>SQL</tytul> <autor>Nowak</autor> <autor>Kubiak</autor> <autor>Lipski</autor> <wydawnictwo> PWN </wydawnictwo> </ksiazka> </bib> Podaj autorów książek w cenie mniejszej niż 60 zł Wynik: <wynik> <nazwisko>Nowak</nazwisko> < nazwisko>Kubiak</nazwisko> </wynik> T. Pankowski 7 <wynik> { for $k in /bib/ksiazka where $k/@cena<60 return $k/autor } </wynik> Wynik: <wynik> <autor>Nowak</autor> <autor>Kubiak</autor> </wynik> T. Pankowski 6 XQuery – sortowanie wyniku <bib> <ksiazka cena="55.00"> <tytul>XML</tytul> <autor>Nowak</autor> <autor>Kubiak</autor> <wydawnictwo> PWN </wydawnictwo> </ksiazka> <ksiazka cena="70.00"> <tytul>SQL</tytul> <autor>Nowak</autor> <autor>Kubiak</autor> <autor>Lipski</autor> <wydawnictwo> PWN </wydawnictwo> </ksiazka> </bib> <wynik> { for $k in /bib/ksiazka where $k/@cena<60 return <nazwisko> { $k/autor/text() } </nazwisko>} } </wynik> Podaj autorów książek w cenie mniejszej niż 60 zł Podaj autorów książek w cenie mniejszej niż 60 zł <wynik> { for $k in /bib/ksiazka where $k/@cena<60 order by $k/@cena return $k/autor } </wynik> Wynik: <wynik> <autor>Nowak</autor> <autor>Kubiak</autor> </wynik> T. Pankowski 8 XQuery – przykład XDM Dla każdego autora PWN podaj wykaz jego książek: <wynik> { for $a in distinct-values(/bib/ksiazka[wydawnictwo/text()="PWN"]/autor/text()) return <wykaz> { $a } { for $t in /bib/ksiazka[autor/text()=$a]/tytul/text() return <tytul>{$t}</tytul> } </wykaz> } </wynik> ¾ XQuery 1.0 and XPath 2.0 Data Model (XDM) ¾ W3C Recommendation 23 January 2007 http://www.w3.org/TR/xpath-datamodel/ ¾Model danych dla: XSLT 2.0, XQuery 1.0, and XPath 2.0 ¾Język jest domknięty ze względu na model, jeśli mamy gwarancję, że wartość każdego wyrażenia należy do modelu. distinct-values = funkcja eliminująca duplikaty T. Pankowski 9 T. Pankowski 10 Definicje modelu XDM Definicje modelu XDM (2) • [Def.1] Każda instancja modelu jest sekwencją • [Def.2] Sekwencja jest uporządkowaną kolekcją jednej lub wielu pozycji (items). Sekwencja nie może należeć do sekwencji. Pojedyncza pozycja traktowana jest jako sekwencja zawierająca jedną pozycję. • [Def.3] Pozycja jest wierzchołkiem (node) lub wartością atomową (atomic value). • [Def. 4] Każdy wierzchołek jest jednym z 7 typów (document (lub • [Def.7] Wartość atomowa należy do przestrzeni wartości typu atomowego i jest etykietowana nazwą tego typu atomowego. • [Def.8] Istnieją 23 pierwotne typy proste (primitive simple types), np.: string, boolean, float, time, date, hexBinary, … • [Def.9] Typ reprezentowany jest za pomocą expanded-QName. • [Def.10] Expanded-QName składa się z trzech części: prefix (może być pusty), URI przestrzeni nazw (może być pusty), nazwy lokalnej. root), element, attribute, text, namespace, processing instruction, comment). Każdy wierzchołek należy do co najwyżej jednego drzewa, • Np.: prefix xs: związany z URI http://www.w3.org/2001/XMLSchema każde drzewo ma dokładnie jeden korzeń. • [Def.5] Drzewo, którego korzeń jest typu Document nazywamy documentem. • [Def.6] Drzewo, którego korzeń nie jest typu Document nazywamy fragmentem. T. Pankowski 11 T. Pankowski 12 Definicje modelu XDM (3) Definicje modelu XDM (4) • Wierzchołki są jednoznaczne, mają tożsamość, są różne od wszystkich innych. Wartości atomowe nie mają tożsamości (identyfikatora); każda instancja wartości "5" jest identyczna z każdą inną instancją "5" (jako integer). • Jednoznaczności wierzchołków nie należy mylić z wartościami unique ID, gdzie wartość tego typu przypisana jest elementowi jako jego nazwa i służy do realizacji referencji typu ID/IDREF. • [Def.11] Uporządkowanie dokumentu jest zdefiniowane pomiędzy wszystkimi wierzchołkami. Jest to porządek całkowity. Nieformalnie, uporządkowanie dokumentu jest zgodne z porządkiem przy jego serializacji. T. Pankowski • [Def.12] Porządek dokumentu jest stabilny, tzn. kolejność wierzchołków nie zmienia się podczas przetwarzania. • Korzeń jest pierwszym wierzchołkiem. • Wierzchołek poprzedza wszystkie swoje dzieci i wszystkie wierzchołki potomne. • Wierzchołek przestrzeni nazw następuje bezpośrednio po wierzchołku elementowym, do którego jest przypisany. • Wierzchołki atrybutowe – po swoim wierzchołku elementowym i ew. po wierzchołku przestrzeni nazw. • Dzieci i potomkowie wierzchołka występują przed jego rodzeństwem. 13 T. Pankowski Język XQuery – sekwencje 1. 2. 3. 4. 5. Język XQuery – wyrażenia Sekwencją jest to uporządkowany ciąg wierzchołków lub wartości atomowych (prostych). Sekwencje nie mogą być zagnieżdżane. Porządek w sekwencji zwracanej przez wyrażenie jest – inaczej niż w SQL – ściśle określony; jest to tzw. porządek dokumentu. Kolejność tę można zmienić żądając sortowania za pomocą klauzuli order by. Sekwencje mogą być wynikiem wyrażeń, można je też zapisać jawnie ujmując elementy, oddzielone przecinkami, w nawiasy zwykłe. Pustą sekwencję zapisuje się w postaci pary nawiasów:(). Na przykład: wynikiem kombinacji a, (a,b) i () jest sekwencja (a,b,c). 1. 2. 3. 15 Wszystkie konstrukcje języka XQuery składają się z wyrażeń. Wyrażenia zwracają sekwencje i mogą być zagnieżdżane. Wyrażenia mogą zawierać: • • • • • • • • 4. T. Pankowski 14 stałe, jawnie zapisane sekwencje, odwołania do zmiennych, wywołania funkcji wbudowanych i funkcji użytkownika, ścieżki XPath, wyrażenia FLWOR, wyrażenia warunkowe, operatory. Wyrażenia wykonywane są w kontekstach wyrażeń, na które składa się informacja mająca wpływ na wynik wyrażenia. Informacja to może tworzyć kontekst statyczny lub kontekst dynamiczny. T. Pankowski 16 Język XQuery – zmienne 1. 2. Zapytania Najprostszym zapytaniem w XQuery jest wyrażenie ścieżkowe XPath. Nazwy zmiennych poprzedzane są znakiem dolara. Zmienne mogą być deklarowane, ale nie jest to obowiązkowe. lub <tytuly> { doc("publik.xml")//tytul } </tytuly> select bib.query(' <tytuly> {//tytul} </tytuly>') from publik daje w wyniku dokument o następującej postaci: <tytuly> <tytul>XML</tytul> <tytul>SQL</tytul> </tytuly> gdyż ścieżka XPath zwraca sekwencję elementów <tytul>. T. Pankowski 17 Zapytania 18 Czym jest XQuery? W rozważanych zapytania ścieżka XPath //tytul zwraca sekwencję elementów typu <tytul>. • W pierwszym zapytaniu odwołano się do zewnętrznego dokumentu jako do źródła danych, a w drugim – do dokumentu w bazie danych (publik.bib). • Tak proste zapytanie daje stosunkowo niewielkie możliwości, dlatego do konstruowania praktycznie przydatnych zapytań najczęściej używa się wyrażeń FLWOR. T. Pankowski T. Pankowski 19 ¾Jest językiem zapytań, który: • wybiera elementy/atrybuty z dokumentu wejściowego, • łączy dane z wielu dokumentów wejściowych, • umożliwia modyfikację danych, • wylicza nowe dane, • umożliwia budowanie dokumentu wynikowego • dodaje nowe elementy/atrybuty do wyniku, • sortuje wynikowy dokument T. Pankowski 20 Związek z innymi językami Wyrażenia FLOWOR Konstruktory XML Prolog zapytań Funkcje użytkownika Wyrażenia warunkowe Wyrażenia arytmetyczne Wyrażenia kwantyfikowane Funkcje i operatory Model danych (XDM) Źródła danych ¾ Dostęp do źródeł danych dla zapytań zapewniają dwie funkcje wbudowane: Arkusze stylów (stylesheets) Szablony (templates) … itd. • • XQuery 1.0 XPath 2.0 XSLT 2.0 ¾ Odwołanie do dokumentu w SQL Server: XPath 1.0 • • Wyrażenia ścieżkowe Wyrażenia logiczne Funkcje T. Pankowski 21 Przykłady @zmienna.query('xquery') kolumna.query('xquery') T. Pankowski 22 DTD – przykład • http://www.w3.org/TR/xmlquery-use-cases T. Pankowski doc(URI) – zwraca (jako wierzchołek dokumentu, korzeń) dokument znajdujący się pod wskazanym adresem URI; collection(URI) – zwraca sekwencję korzeni dokumentów będących wynikiem odwołania się do wskazanego adresu URI. <!ELEMENT bib (książka* )> <!ELEMENT książka (tytuł, (autor+ | editor+ ), wydawnictwo, cena )> <!ATTLIST książka rok CDATA #REQUIRED > <!ELEMENT autor (nazwisko, imię )> <!ELEMENT editor (nazwisko, imię, afiliacja )> <!ELEMENT tytuł (#PCDATA )> <!ELEMENT nazwisko (#PCDATA )> <!ELEMENT imię (#PCDATA )> <!ELEMENT afiliacja (#PCDATA )> <!ELEMENT wydawnictwo (#PCDATA )> <!ELEMENT cena (#PCDATA )> 23 T. Pankowski 24 bib książka* @rok tytuł autor+ imię nazwisko edytor+ wydawnictwo cena imię nazwisko afiliacja <!ELEMENT bib (książka* )> <!ELEMENT książka (tytuł, (autor+ | edytor+ ), wydawnictwo, cena )> <!ATTLIST książka rok CDATA #REQUIRED > <!ELEMENT autor (imię, nazwisko )> <!ELEMENT editor (imię, nazwisko, afiliacja )> <!ELEMENT tytuł (#PCDATA )> <!ELEMENT imię (#PCDATA )> <!ELEMENT nazwisko (#PCDATA )> <!ELEMENT afiliacja (#PCDATA )> <!ELEMENT wydawnictwo (#PCDATA )> <!ELEMENT cena (#PCDATA )> <bib> <książka rok="1994"> <tytuł>TCP/IP Illustrated</tytuł> <autor><imię>W.</imię><nazwisko>Stevens</nazwisko></autor> <wydawnictwo>Addison-Wesley</wydawnictwo> <cena> 65.95</cena> </książka> <książka rok="1992"> <tytuł>Advanced Programming in the Unix</tytuł> <autor><imię>W.</imię><nazwisko>Stevens</nazwisko></autor> <wydawnictwo>Addison-Wesley</wydawnictwo> <cena>65.95</cena> </książka> <książka rok="2000"> <tytuł>Data on the Web</tytuł> <autor><imię>Serge</imię><nazwisko>Abiteboul</nazwisko></autor> <autor><imię>Peter</imię><nazwisko>Buneman</nazwisko></autor> <autor><imię>Dan</imię><nazwisko>Suciu</nazwisko></autor> <wydawnictwo>Morgan Kaufmann</wydawnictwo> <cena> 39.95</cena> </książka> <książka rok="1999"> <tytuł>The Economics of Technology for Digital TV</tytuł> <editor> <imię>Darcy</imię><nazwisko>Gerbarg</nazwisko> <afiliacja>CITI</afiliacja> </editor> <wydawnictwo>Kluwer Academic</wydawnictwo> <cena>129.95</cena> </książka> </bib> Q1: Podaj książki wydane przez Addison-Wesley po roku 1991, uwzględnij rok wydania i tytuł Przykład: Q1 bib książka* $k @rok $r tytuł $t autor+ imię nazwisko Q1: Podaj książki wydane przez Addison-Wesley po roku 1991, uwzględnij rok wydania i tytuł edytor+ wydawnictwo cena $w imię nazwisko afiliacja XQuery: bib książka* @rok $r tytuł $t <bib>{ for $k in /bib/książka, $r in $k/@rok, $t in $k/tytuł/text(), $w in $k/wydawnictwo where $w = "Addison-Wesley" and $r > 1991 return <książka rok="{$r}"> <tytuł>{$t}</tytuł> </książka>} </bib> select Dok.query(' <bib> { for $k in /bib/książka where $k/wydawnictwo = ''Addison-Wesley'' and $k/@rok > 1991 return <książka rok="{ $k/@rok }"> { $k/tytuł } </książka> } </bib>') from Tab T. Pankowski 28 Przykład: Q1 Przykład: Q2 Q1: Podaj książki wydane przez Addison-Wesley po roku 1991, uwzględnij rok wydania i tytuł select Dok.query(' <bib> { for $k in /bib/książka where $k/wydawnictwo = ''Addison-Wesley'' and $k/@rok > 1991 return <książka rok="{ $k/@rok }"> { $k/tytuł } </książka> } </bib>') from Tab @rok Q2: bib wyniki książka* $k wynik* $a imię nazwisko XQuery: edytor+ wydawnictwo cena $w imię nazwisko afiliacja <wyniki>{ for $k in /bib/książka, $t in $k/tytuł return <wynik> {$t} { for $a in $k/autor return $a } </wynik>} </wyniki> książka* $k wynik* tytuł $t autor+ $a ZF: tytuł Æ wynik edytor+ $a wydawnictwo cena $w imię nazwisko afiliacja autor $a tytuł $t ZF: autur,tytuł Æ wynik <wyniki>{ for $k in /bib/książka, $t in $k/tytuł, $a in $k/autor return <wynik> {$t} {$a} </wynik>} T. Pankowski </wyniki> 29 Przykład: Q3 autor+ wyniki autor+ XQuery: Q2: Dla każdej książki podaj w elemencie "wynik" jej tytuł i listę jej autorów. tytuł $t tytuł $t bib imię nazwisko <bib> <książka rok="1994"> <tytuł>TCP/IP Illustrated</tytuł> </książka> <książka rok="1992"> <tytuł>Advanced Programming in the Unix</tytuł> </książka> </bib> T. Pankowski @rok Q2: Utwórz płaską listę wszystkich par tytuł-autor, gdzie każda para należy do elementu "wynik" Q3: 30 Przykład: Q4 Q4: Q2: Dla każdego autora podaj wykaz tytułów jego książek. @rok tytuł $t bib wyniki książka* $k wynik* autor+ edytor+ $a imię nazwisko wydawnictwo cena $w imię nazwisko afiliacja autor $a tytuł+ $t ZF: autor Æ wynik ZF: tytuł Æ książka XQuery: <wyniki>{ for $a in distinct-values(/bib/książka/autor) return <wynik> {$a} { for $t in /bib/książka[autor=$a]/title return $t } </wynik>} </wyniki> T. Pankowski Przykład: Q6 34 Przykład: Q12 Q6: Dla każdej książki podaj jej tytuł oraz co najwyżej dwóch pierwszych autorów. Jeśli autorów jest więcej niż dwóch, to wypisz pusty element ze znacznikiem "i-inni". <bib> { for $k in //książka where count($k/autor) > 0 return <książka> { $k/tytuł } { for $a in $k/autor[position()<=2] return $a } { if (count($k/autor) > 2) then <i-inni/> else () } </książka> } </bib> 35 Q12: Podaj pary książek, które mają tych samych autorów <bib> { for $k1 in //książka, $k2 in //książka let $aut1 := $k1/autor , $aut2 := $k2/autor where $k1 < $k2 and $k1/tytuł != $k2/tytuł and $aut1=$aut2 return <para> { $k1/tytuł } { $k2/tytuł } </para> } </bib> 36 Zapytania rekurencyjne Dokument wejściowy • Przykład pokazuje, w jaki sposób można użyć zapytanie rekurencyjne do skonstruowania dokumentu hierarchicznego o dowolnej głębokości ze struktury płaskiej. DTD: Przykładowe dane: T. Pankowski Dokument wynikowy DTD: <!DOCTYPE Hierarchia [ <!ELEMENT Hierarchia (Część*)> <!ELEMENT Część(Część*)> <!ATTLIST Część IdCz CDATA #REQUIRED Nazwa CDATA #REQUIRED> ]> Dokument wynikowy: 37 <!DOCTYPE Lista [ <!ELEMENT Lista (Część*)> <!ELEMENT Część EMPTY> <!ATTLIST Część IdCz CDATA #REQUIRED NależyDo CDATA #IMPLIED Nazwa CDATA #REQUIRED> ]> <Lista> <Część <Część <Część <Część <Część <Część <Część <Część <Część <Część </Lista> IdCz="0" Nazwa="samochód"/> IdCz="1" NależyDo="0" Nazwa="silnik"/> IdCz="2" NależyDo="0" Nazwa="drzwi"/> IdCz="3" NależyDo="1" Nazwa="cylinder"/> IdCz="4" NależyDo="2" Nazwa="okno"/> IdCz="5" NależyDo="2" Nazwa="zamek"/> IdCz="10" Nazwa="hulajnoga"/> IdCz="11" NależyDo="10" Nazwa="deska"/> IdCz="12" NależyDo="10" Nazwa="kółko"/> IdCz="20" Nazwa="kajak"/> T. Pankowski 38 Program w XQuery (implementacja: Stylus Studio) declare function local:one_level($p as element()) as element() { <Część IdCz="{ $p/@IdCz }" Nazwa="{ $p/@Nazwa }" > { for $s in doc("ListaCz.xml")//Część where $s/@NależyDo = $p/@IdCz return local:one_level($s) } </Część> }; <Hierarchia> { for $p in doc("ListaCz.xml")//Część[empty(@NależyDo)] return local:one_level($p) } </Hierarchia> T. Pankowski 40