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