XQuery Interrogation d’arbres XML ou SQL du futur
Introduction C’est quoi Xquery ? Langage pour interroger les données (arbres) XML = requêtes, plus pour interroger (et trouver des éléments) que pour transformer – plus souple que XSL qui est plus une transformation d’arbre XML, mais utilisant tous les deux les expressions XPath Semblable à SQL pour les B.D., sauf que SQL : – travaille sur des bases relationnelles : données fortement en relation dans des tables ou dans des arbres à x niveaux contraints – base ses requêtes sur la recherche de ces relations fortes
Introduction En quoi les données XML sont-elles différentes ? Les données relationnelles (SQL) sont denses – Chaque rangée a une valeur dans chaque colonne – Problème des valeurs nulles Ce n’est pas le cas de XML qui peut avoir : – des éléments vides – des éléments absents C’est un degré de liberté supérieur pour XML C’est pourquoi on appelle les documents XML : semi-structurés
Introduction En quoi les données XML sont-elles différentes ? " " En XML, il est naturel de chercher de manière indépendante du niveau – Exemple : trouver tout ce qui est rouge //*[@couleur = " rouge " ] En relationnel (SQL) : tout est uniforme et répétitif – Tous les comptes en banque ont une structure similaire – Les méta-informations peuvent être stockées à part XML : très variable ! – Chaque page Web est différente – Chaque objet XML doit se décrire, les méta-données sont dans le document Exemple : trouver tous les éléments qui ont le contenu identique à leur nom //*[name(.) = string (.)]
Introduction En quoi les requêtes XML sont-elles différentes ? Les requêtes SQL retournent des ensembles de résultats homogènes Les résultats d’une requête XML peuvent être de type différent, et de structures complexes Exemple : //*[couleur="rouge"] peut retourner une cerise, une voiture, un drapeau… On retrouve côte à côte des éléments et des valeurs atomiques (mixité) Les requêtes XML doivent pouvoir effectuer des transformations structurelles Exemple : – inverser l’ordre dans une hiérarchie Ce qui n’est pas forcément autorisé en SQL
Introduction En quoi les requêtes XML sont-elles différentes ? Importance de l’ordre – En SQL L’ordre est bien ciblé sur un ensemble bien sélectionné de valeur, de part sa fonction ou ses relations dans la base select nom, prenom from etudiants order by nom – En XML L’ordre apparaît à plusieurs niveaux – Trouver le 5e arrêt – Trouver les outils utilisés avant le marteau – Conséquences : En XML, les requêtes doivent prendre l’ordre en compte
Introduction En conclusion XML est très différent de SQL, – et justifie donc le fait de vouloir un langage de requêtes dédié Mais la tâche n’est pas simple …
Introduction XQuery est un sur-ensemble de SQL XQuery Les fonctionnalités de SQL sur les tables sont étendues pour supporter des opérations sur des arbres XQuery Questions Recherche tabulaires d'information Structure d'arbres
Introduction Les extensions par rapport à SQL sont : Extraction de sous-arbres : Xpath Sélection de sous-arbres en utilisant des prédicats : Xpath Des variables sont utilisées pour mémoriser un arbre ou pour itérer sur des collections d’arbres Les arbres extraits peuvent être combinés en utilisant des jointures Les arbres peuvent être réordonnés Des fonctions utilisateurs peuvent être définies et intégrées n’importe où dans les requêtes
Introduction Xpath XQuery Xpath 1.0 permet d'exprimer des requêtes de filtrage sur des arbres Il n'est pas possible : – de créer des nœuds, – de construire des arbres/des documents nouveaux, – de trier des nœuds, ... – Il est difficile d'exprimer des jointures (pas de variables). XQuery XQuery est un langage de requêtes complet qui permet : – de créer des nœuds et de construire des arbres nouveaux, – de définir et d'instancier des variables, – de définir des fonctions, ...
Introduction Xquery en 1 transparent Proposé par IBM et les auteurs de XML/QL Soutenu par Microsoft Tout Xpath est une requête valide Forme de requête FLWR dans des forêts FOR $<var> in <forest> [, $<var> in <forest> ]… // itération LET $<var> := <subtree> // affectation WHERE <condition> // filtrage RETURN <result> // construction Les forêts sont sélectionnées par des Xpath Le résultat est une forêt
Plan XQuery Forme d’une requête Contexte des expressions Annotations de type Valeurs d’un nœud Typage statique et dynamique Conversions Expressions
Forme d’une requête Définition : Forme 1 : Expressions simples : Une requête XQuery est une composition d’expressions Chaque expression a une valeur ou retourne une erreur Forme 1 : Expressions simples : Valeurs atomiques : 46, ‘‘Salut’’ Valeurs construites : true(), date("23-04-2006") Forme 2 : Expressions (requêtes) complexes : Expressions de chemins (XPath) FILM//ACTEUR Expressions FLWR For-Let-Where-Return Tests if-then-return-else-return
Forme d’une requête Fonctions – Racines : – Fonctions prédéfinies : document("url") : retourne le nœud racine du document identifié par l’URI url document("books.xml")//book/author – Fonctions prédéfinies : Celles définies par Xpath – Fonctions utilisateurs
Expressions simples opérations Opérateurs arithmétiques : 1+2 , 3.4-6.5 ,$y mod 2 Opérations sur les séquences : – concaténation : (1, 2, 3) 1 2 3 (1,'A') ou concat('1',’A') 1A (1, (2, 3), ( ), (4)) 1 2 3 4 5 to 8 5 6 7 8 – union, intersection, différence de séquences de nœuds document("books.xml")//book/(@title union price) Opérateurs de comparaison pour valeurs atomiques, nœuds et séquences //examen/note[@num=$a]/text() Opérations booléennes : $x=2 and $y=4 or not($z)
Exemple de documents : books.xml </year> <?xml version="1.0" encoding="ISO-8859-1"?> < book category =" WEB "> <!-- Edited with XML Spy v4.2 --> < title lang =" en "> XQuery Kick Start < bookstore > </ title > < book category =" COOKING "> < author > James McGovern </ author > < title lang =" en "> Everyday Italian < author > Per Bothner </ author > </ title > < author > Kurt Cagle </ author > < author > Giada De Laurentiis < author > James Linn </ author > </ author > < author > Vaidyanathan Nagarajan < year > 2005 </ year > </ author > </year> < price > 30.00 </ price > < year > 2003 </ book > < price > 49.99 </ price > < book category =" CHILDREN "> </ book > < title lang =" en "> Harry Potter < book category =" WEB "> </ title > < title lang =" en "> Learning XML </ title> < author > J K. Rowling </ author> < author > Erik T. Ray </ author > < year > 2005 </ year > < year > 2003 </ year > < price > 29.99 </ price > < price > 39.95 </ price > </ book > </ book > </ bookstore >
Expressions de chemin Expressions régulières Accès via un attribut Liste de tous les auteurs document("books.xml")//book/author Auteur du premier livre document("books.xml")//book[1]/author Liste de tous les auteurs et prix document("books.xml")// book/(author, price) ou document("books.xml")//book/(descendant::author, descendant::price) Accès via un attribut Liste des prix des livres qui ont un attribut title document("books.xml")//book/(@title union price)
Expressions de chemin Liste des livres sauf le dernier Résultat : <book category="WEB"> document("books.xml")//book[position() lt <title lang="en">XQuery Kick last()] Start</title> Résultat : <author>James <book category="COOKING"> McGovern</author> <title lang="en">Everyday Italian</title> <author>Per Bothner</author> <author>Giada De Laurentiis</author> <author>Kurt Cagle</author> <year>2005</year> <author>James Linn</author> <price>30.00</price> <author>Vaidyanathan </book> Nagarajan</author> <book category="CHILDREN"> <year>2003</year> <title lang="en">Harry Potter</title> <price>49.99</price> <author>J K. Rowling</author> </book> <year>2005</year> <price>29.99</price> </book>
Expressions de chemin Sélection Forme : chemin[prédicat] Requête : livre dont le prix est < à 30 document("books.xml")/bookstore/book[price<30] Résultat : <book category="CHILDREN"> <title lang="en">Harry Potter</title> <author>J K. Rowling</author> <year>2005</year> <price>29.99</price> </book>
Expressions de chemin sélection Forme : chemin[prédicat]suite-chemin Requête : titre du livre dont le prix est > à 30 document("books.xml")/bookstore/book[price>30]/title Résultat : <title lang="en">XQuery Kick Start</title> <title lang="en">Learning XML</title>
Autre exemple : bib.xml
Construction de nœuds Construction de nœuds Requête : nom des auteurs du 2ème livre <auteurs> { document("bib.xml")//book[2]/author/la } </auteurs> Résultat : <auteurs> <la>Rigaux</la> <la>Scholl</la> <la>Voisard</la> </auteurs>
Construction de nœuds L’expression contient une exception Requête : tous les sous-éléments des livres sauf les auteurs <book> Tous les sous-éléments sauf les auteurs : { document("bib.xml")//book[1]/(* except author) } </book> Résultat : <book> Tous les sous-éléments sauf les auteurs : <Publisher>O’Reilly</Publisher> <price>28.95</price> </book>
construction de nœuds Construction par transformation de nœud vers valeur Requête : auteurs du premier livre "Les auteurs du premier livre sont,", document("bib.xml")//book[1]/author/la/text() Résultat : Les auteurs du premier livre sont, Amann Rigaux
Expressions Xquery Extraction par comparaison de valeurs atomiques Requête : auteur dont le nom est Scholl document("bib.xml")//book/author[la eq "Scholl"] Résultat : <author> <la>Scholl</la> <fi>M.</fi> </author>
Expressions Xquery Identification du nœud par comparaison de séquences : s = s 1 2 – s’il existe au moins un élément dans s qui est égal à un 1 élément dans s 2 Requête : livres dont l’un des auteurs est Scholl ou Rigaux document("bib.xml")//book[author/la =("Scholl", "Rigaux")] "[" remplace ici le Where Résultat : – Les deux livres Requête : On peut tout simplement compter count(document("bib.xml")//book[author/la =("Scholl", "Rigaux")]) Résultat : 2
Expressions Xquery Identification du nœud par comparaison de l’identité de deux nœuds – n is n n est identique à n 1 2 1 2 Requête : livre dont le 2ème auteur est le dernier de la liste document("bib.xml")//book[author[2] is author[last()]] Résultat : <book title="Comprendre XSLT"> <author> <la>Amann</la> <fi>B.</fi> </author> <author> <la>Rigaux</la> <fi>P.</fi></author> <publisher>O’Reilly</publisher> <price>28.95</price> </book>
Expressions Xquery Nœud résultat de comparaison de la position de deux nœuds : – n << n (n >> n ) n apparaît avant (après) n 1 2 1 2 1 2 Requête : titre du livre dont l’auteur Abiteboul est avant l’auteur Suciu <livre> { document("bib.xml")//book[author[la="Abiteboul"] << author[la="Suciu"]]/@title } </livre> Résultat : <livre title="Data on the Web"/>
Notion de variable Affectation : Let Let $variable := expression Xpath – permet d’associer à une variable une liste de nœuds résultant de l’évaluation d’une expression Xpath Exemple : let $R := document("restaurants.xml")//restaurant return(count($R)) Résultat 2 Exemple : on peut bien sûr l’utiliser pour une valeur simple let $x:=4 return($x*25) Résultat 200
Expressions Xquery Affectation de variables : for et let La clause for $var in exp affecte la variable $var successivement avec chaque item dans la séquence retournée par exp. La clause let $var := exp affecte la variable $var avec la séquence “entière” retournée par exp. Requête : for $b in document("bib.xml")//book[1] let $al := $b/author return <livre nb_auteurs="{count($al)}"> { $al } </livre> Résultat : <livre nb_auteurs="2"> <author><la>Amann</la><fi>B.</fi></author> <author><la>Rigaux</la><fi>P.</fi></author> </livre>
Expressions Xquery Affectation de variables : for et let Requête for $x in (1 to 5) return <test>{$x}</test> Résultat <test>1</test> <test>2</test> <test>3</test> <test>4</test> <test>5</test>
Expressions Xquery Affectation de variables : for et let Requête for $x at $i in document("books.xml")/bookstore/book/title return <book>{xi}. {data($x)}</book> Résultat <book>1. Everyday Italian</book> <book>2. Harry Potter</book> <book>3. XQuery Kick Start</book> <book>4. Learning XML</book>
Expressions Xquery Affectation de variables : for et let Requête let $x := (1 to 5) return <test>{$x}</test> Résultat <test>12345</test>
Expressions XQuery Affectation de variables : for et let Différence entre le for et le let Exemple 1 : for $f in document(“Films.xml")//FILMS/FILM return count($f) retourne 1 1 1 1 1 … car count fonctionne que sur le film en cours Exemple 2 for $f in document("Films.xml")//FILMS let $r:=count($f/FILM) return $r retourne le bon nombre car on placé l’ensemble des films dans $r et count fonctionne sur cet ensemble
Expressions Xquery Sélection : Where La clause Where exp permet de filtrer le résultat par rapport au résultat booléen de l’expression : exp (= prédicat dans l’expression de chemin) Requête : for $x in document("books.xml")/bookstore/book Where $x/price>30 return $x/title Résultat : <title lang="en">XQuery Kick Start</title> <title lang="en">Learning XML</title>
Expressions Xquery Sélection : Where Autre exemple Requête : <livre> { for $a in document("bib.xml")//book Where $a/author[1]/la eq "Abiteboul" return $a/@title} </livre> Résultat : <livre title="Data on the Web"/>
Expressions Xquery Sélection : Where Autre exemple Requête : lister les meilleurs restaurants de Paris for $x in document("restaurants.xml")//Restaurant Where ($r/Comments,"Bon") or ($r/Comments, "Excellent") and $r/Adresse/Ville = "Paris" return $r/Nom Résultat : <Nom>Le Moulin</Nom> <Nom>La Licorne</Nom>
Expressions Xquery Trier par : order by Trier par ordre alphabétique sur le titre Requête : for $x in document("books.xml")/bookstore/book Where $x/price>30 order by $x/title return $x/title Résultat : <title lang="en">Learning XML</title> <title lang="en">XQuery Kick Start</title>
Expressions Xquery Trier par : order by Autre manière de trier par ordre alphabétique sur le titre Requête : for $x in document("books.xml")/bookstore/book/title order by $x return $x Résultat : <title lang="en">Everyday Italian</title> <title lang="en">Harry Potter</title> <title lang="en">Learning XML</title> <title lang=“en">XQuery Kick Start</title>
Expressions Xquery Tri et construction d’éléments Requête : <ul> { for $x in document("books.xml")/bookstore/book/title order by $x return <li>{$x}</li> } </ul> Résultat : <ul> <li><title lang="en">Everyday Italian</title></li> <li><title lang="en">Harry Potter</title></li> <li><title lang="en">Learning XML</title></li> <li><title lang="en">XQuery Kick Start</title></li> </ul>
Expressions Xquery Tri et construction d’éléments Requête : <ul> { for $x in document("books.xml")/bookstore/book/title order by $x return <li>{data($x)}</li> } </ul> Résultat : <ul> <li>Everyday Italian</li> <li>Harry Potter</li> <li>Learning XML</li> <li>XQuery Kick Start</li> </ul>
Expressions XQuery Test : if – then - else Requête : for $x in document(“books.xml")/bookstore/book return if ($x/@category="CHILDREN") then <child>{data($x/title)}</child> else <adult>{data($x/title)}</adult> Résultat : <adult>Everyday Italian</adult> <child>Harry Potter</child> <adult>XQuery Kick Start</adult> <adult>Learning XML</adult>
Expressions Xquery Test : if – then - else Requête: <livres> { for $b in document("bib.xml")//book Where $b/author/la = "Rigaux" return if ($b/@year > 2000) then <livre recent="true"> {$b/@title} </livre> else <livre> {$b/@title} </livre> } </livres> Résultat: <livres> <livre title="Comprendre XSLT"/> <livre recent="true" title="Spatial Databases"/> </livres>
Expressions Xquery Quantification $var in expr1 satisfies expr2 il existe au moins un nœud retourné par l’expression expr1 qui satisfait l’expression expr2 every $var in expr satisfies expr tous les nœuds retournés par l’expression expr1 satisfont l’expression expr2 Requête : for $a in document("bib.xml")//author where every $b in document("bib.xml")//book[author/la = $a/la] satisfies $b/publisher="Morgan Kaufmann Publisher" return string($a/la) Résultat : Scholl, Voisard, Abiteboul, Buneman, Suciu
Expressions Xquery enchaînement de plusieurs requêtes Exemple Enchaîner plusieurs for Syntaxe for $f in document(…)//… Where … return for $y in $f/…/… Exemple for $x in document("Films.xml")//FILM Where empty($x/RESUME) return string($x/TITRE) for $x in document("Films.xml")//FILM Where empty($x/RESUME) return data($x/TITRE)
Expressions Xquery Enchaînement de plusieurs requêtes Mettre les requêtes les unes derrière les autres Exemple : let $f:= document("Films.xml")//FILMS let $r:=count($f/FILM) return $r
Expressions Xquery Enchaînement de plusieurs requêtes Mettre les requêtes les unes derrière les autres Exemple : let $f:= document("Filmx.xml")//FILMS let $r:=count($f/FILM) return $r Attention si plusieurs for chaque for doit se terminer correctement : par un return for $f in document("Films.xml")//FILM Where $f/TITRE="Reservoir dogs" return For $r in $f/ROLES/ROLE Where $r/PRENOM="Harvey" and $r/NOM="Keitel" return $r/INTITULE
Expressions Xquery Enchaînement de plusieurs requêtes Autre forme d’enchaînement : for sur plusieurs variables for $f in document(…) (… …), $y in $f/… (… …) Exemple 1 for $f in document("Films.xml")//FILM, $r in $f/RESUME //similaire à $f/RESUME existe return $f/TITRE Exemple 2 for $x in document("Films.xml")//FILM, $y in $x/ROLES where ($y/ROLE/PRENOM ="James" and $y/ROLE/NOM = "Stewart") and ($y/ROLE/PRENOM ="Kim" and $y/ROLE/NOM = "Novak") return $x/TITRE
Jointure Utilisation de plusieurs documents Requête : Recherche dans deux Résultat : fichiers : qui a mis en scène le film <ARTISTE> Eyes Wide Shut ? <ACTNOM>Kubrick</ACTNOM> <ARTISTE> <ACTPNOM>Stanley</ACTPNOM> { for </ARTISTE> $f in document("Films.xml")//FILM, $ms in document("Artistes.xml")//ARTISTE Where $f/MES/@idref=$ms/@id and $f/TITRE="Eyes Wide Shut" return ($ms/ACTNOM,$ms/ACTPNOM) } </ARTISTE>
Jointure Utilisation de plusieurs documents Requête : films où le metteur en scène Résultat participe comme acteur <LISTESFILMS> <LISTESFILMS> <FILM> { <TITRE>Impitoyable</TITRE> for </FILM> $ms in <FILM> document("Artistes.xml")//ARTISTE, $f in document("Films.xml")//FILM, <TITRE>Les pleins $r in $f/ROLES/ROLE pouvoirs</TITRE> Where </FILM> $r/MES/@idref=$ms/@id <FILM> and $r/PRENOM=$ms/ACTPNOM <TITRE>Reservoir dogs</TITRE> and $r/NOM=$ms/ACTNOM </FILM> return <FILM>{$f/TITRE}</FILM> </LISTESFILMS> } </LISTESFILMS>
Définition de fonctions Déclaration declare function nom ($arg1 as type1, $arg2 as type2, ...) as type_retour { corps de la fonction }; Le nom de la fonction doit être préfixé. Il existe un préfixe créé par défaut : local Les types peuvent être : – text(), comment(), processing-instruction() – element(), attribute() - le nom peut être spécifié entre les parenthèses – xs: type , où type est un type défini dans la norme XML Schema , par exemple xs:string, xs:boolean, xs:number, xs:integer Un type peut être suivi de *, + ou ? afin d'exprimer le fait de pouvoir gérer une séquence d'éléments au lieu d’un seul élément
Définition de fonctions Exemple declare function local:minPrice( $price as xs:decimal?, $discount as xs:decimal?) as xs:decimal? { let $disc := ($price * $discount) div 100 return ($price - $disc) }; Appel <minPrice>{local:minPrice(24,45)}</minPrice> Résultat : <minPrice>13.20 </minPrice>