Département : Génie de l’informatique et mathématiques
Filière: Génie informatique
XQuery
Professeur: Mohamed OUHDA Ouhda,med@gmail,com
XQUERY, UN LANGAGE DE REQUÊTE
XQuery, langage non XML, permet de traiter des
ressources XML (fichier ou SGBD-XML) pour obtenir
des structures XML. C'est un langage fonctionnel
typé et basé sur la manipulation de liste de noeuds
XML.
REQUÊTE XQUERY
⚫ XQuery peut être vu comme un langage fonctionnel manipulant des séquences
d'items.
⚫ Une requête XQuery est donc une expression portant sur des items (séquences
d'arbres XML ou de valeurs atomiques).
⚫ Chaque expression retourne une valeur
⚫ Une expression peut être :
◦ une valeur atomique, un noeud XML ou une séquence ;
◦ une variable;
◦ une expression arithmétique ou logique (les opérateurs de base sont ceux d'XPath
2.0) ;
◦ une union, intersection ou différence de séquences ;
◦ une requête XPath 2.0 ;
◦ une fonction prédéfinie ou définie en local;
◦ un des opérateurs spécifiques (alternative "if-then-else", boucle, etc.).
EXEMPLE DE <?xml version="1.0" encoding="UTF-8"?>
<factures>
FICHIER XML : <facture num="1" dateFacture="2006-1-1">
<client codeClient="c1" societe="AGFA"/>
[Link] <detail>
<produit designation="PC212" quantite="12" prixUnitaire="6700" montant="80400"/>
L <produit designation="Imp11" quantite="3" prixUnitaire="1700" montant="5100"/>
<produit designation="Papier" quantite="22" prixUnitaire="40" montant="880"/>
</detail>
</facture>
<facture num="2" dateFacture="2006-11-1">
<client codeClient="c2" societe="MITAL"/>
<detail>
<produit designation="Inf33" quantite="11" prixUnitaire="3400" montant="37400"/>
<produit designation="TVLCD52" quantite="6" prixUnitaire="9000" montant="54000"/>
</detail>
</facture>
<facture num="3" dateFacture="2006-12-11">
<client codeClient="c2" societe="MITAL"/>
<detail>
<produit designation="Inf33" quantite="11" prixUnitaire="3400" montant="37400"/>
<produit designation="TVLCD52" quantite="6" prixUnitaire="9000" montant="54000"/>
</detail>
</facture>
</factures>
EXEMPLE 1 DE XQUERY
<resultat>
{
doc("[Link]")/factures/facture[@num=1]
}
</resultat>
⚫Retourne la facture numéro 1 du documents [Link]
<?xml version="1.0" encoding="UTF-8"?>
<resultat>
<facture num="1" dateFacture="2006-1-1">
<client codeClient="c1" societe="AGFA"/>
<detail>
<produit designation="PC212" quantite="12" prixUnitaire="6700" montant="80400"/>
<produit designation="Imp11" quantite="3" prixUnitaire="1700" montant="5100"/>
<produit designation="Papier" quantite="22" prixUnitaire="40" montant="880"/>
</detail>
</facture>
</resultat>
EXEMPLE 2 DE XQUERY
<resultat>
{
sum(doc("[Link]")/factures/facture[@num=1]/detail/produit/@montant)
}
</resultat>
⚫Retourne la somme des montant des produits de la facture numéro 1
<?xml version="1.0" encoding="UTF-8"?>
<resultat>86380</resultat>
EXEMPLE 3 XQUERY
<resultat>
{
for $f in doc("[Link]")/factures/facture return
<totalFacture num="{$f/@num}">{ sum($f/detail/produit/@montant)}
</totalFacture>
}
</resultat>
⚫Retourne la somme des montant des produits de chaque facture.
<?xml version="1.0" encoding="UTF-8"?>
<resultat>
<totalFacture num="1">86380</totalFacture>
<totalFacture num="2">91400</totalFacture>
<totalFacture num="3">91400</totalFacture>
</resultat>
EXEMPLE 4 XQUERY
<resultat> {
for $f in doc("[Link]")/factures/facture let
$total:=sum($f/detail/produit/@montant) where
$total>90000
return
<totalFacture num="{$f/@num}">{$total}</totalFacture>
}</resultat>
⚫Retourne la somme des montant des produits des factures dont le total est
supérieur à 90000
<?xml version="1.0" encoding="UTF-8"?>
<resultat>
<totalFacture num="2">91400</totalFacture>
<totalFacture num="3">91400</totalFacture>
</resultat>
REQUÊTE XQUERY
⚫Une requête XQuery est composée de trois
parties :
◦ une ligne d'entête commencée par "xquery" et
contenant la version et, éventuellement xquery version "1.0" encoding "utf-8";
l'encodage du document ;
🞄 xquery version "1.0" encoding "utf-8";
Déclarations
◦ un ensemble de déclarations :
déclarations de variables ou constantes,
🞄
déclarations de fonctions utilisateur locales,
🞄
Expressions XQuery
importation de modules (bibliothèques XQuery),
🞄
détermination du schéma du résultat,
🞄
🞄 détermination des espaces de nom et de leur utilisation,
🞄 détermination du format du résultat et autres paramètres ;
◦ l'expression XQuery à exécuter.
⚫La ligne d'entête et les déclarations sont toutes
terminées par ";".
OPÉRATEURS DE XQUERY
⚫ Les opérateurs arithmétiques et logiques sont les mêmes que ceux de XPath 2.0.
◦ Opérateurs de comparaison sur les valeurs atomiques ("eq", "ne", "gt", "ge", "lt", "le") et sur les
séquences ("=", "!=", ">", ">=", "<", "<=").
◦ Des opérateurs existent aussi sur les noeuds ("is", "isnot", "<<", ">>").
⚫ XQuery exploite aussi les opérateurs déjà proposés par XPath 2.0 comme :
◦ l'alternative avec "if (condition) then Seq1 else Seq2" où, contrairement à beaucoup de langages,
le "else" est obligatoire ;
◦ la quantification existentielle avec "some $v in Seq satisfies exp($v)" qui sera satisfaite si au
moins un item de "Seq" satisfait l'expression booléenne "exp" ;
◦ la quantification universelle avec "every $v in Seq satisfies exp($v)" qui sera satisfaite si
tous les items de "Seq" satisfont l'expression booléenne "exp".
⚫ XQuery propose un opérateur fondamental pour combiner des informations : l'opérateur FLWOR .
Il peut être mis en comparaison avec le célèbre "select" de SQL.
OPÉRATEUR FLWOER
⚫L'opérateur FLWOR est un opérateur complexe qui permet de
parcourir une ou plusieurs séquences (et d'effectuer ainsi des
opérations de type "jointure").
⚫La forme de cet opérateur comprend un certain nombre de
clauses dans l'ensemble suivant (la première lettre de chacune
des clauses forme le sigle FLWOR) :
◦ for
◦ let
◦ where
◦ order by
◦ return
LA CLAUSE FOR
⚫permet de parcourir une ou plusieurs séquences en positionnant la
valeur d'autant de variables.
⚫Une variable XQuery commence par un "$".
⚫Si plusieurs séquences sont présentes, la clause parcourra le produit
cartésien des différentes séquences.
⚫Cette clause est de la formes :
◦ for $v1 in Seqf1, $v2 in Seqf2, … $vn in Seqfn'.
⚫Exemple :
◦ for $i in (1 to 3), $j in (4 to 6)
LA CLAUSE LET
⚫La clause "let" permet de positionner des variables
"locales" au n-uplet courant.
⚫Cette clause permet souvent de simplifier grandement les
filtres, voire la génération du résultat.
⚫Elle est de la forme :
◦ let $loc1 := $Seql1, $loc2 := $Seql2, …, $locm := $Seqlm
LA CLAUSE WHERE
⚫La clause "where" est une clause de filtre.
⚫Elle permet de ne sélectionner que les n-uplets qui satisfont à
l'expression booléenne qu'elle décrit.
⚫Cette expression comporte donc nécessairement une ou plusieurs
variables d'une clause "for" ou d'une clause "let" précédente.
⚫Elle est de la forme :
◦ where cond($v1, $v2, ..., $vn, $loc1, $loc2, ..., $locm)
LA CLAUSE ORDER BY
⚫La clause "order by" décrit un critère d'ordre pour la
séquence de valeurs qui sera générée, fonction des variables
des clauses "for" ou "let".
⚫Elle est de la forme :
◦ order by $critère1 dir1, …, $critèrep dirp
⚫où les "diri" sont pris dans { ascending,
descending}.
⚫Ce dernier peut être suivit de
◦ "empty greatest" ou "empty least".
LA CLAUSE RETURN
⚫La clause "return" permet de construire un résultat pour
chacun des n-uplets.
⚫Elle est de la forme
◦ return exp
◦ où "exp" est une expression XQuery.
EXEMPLE 1 DE FLOWER
for $i in (1 to 3), $j in (4 to
6) let $k:= ($i to $ j)
return <res>{$i}/{$j}/{$k}</res>
⚫Produit le résultat suivant :
<?xml version="1.0" encoding="UTF-
8"?>
<res>1/4/1 2 3 4</res>
<res>1/5/1 2 3 4 5</res>
<res>1/6/1 2 3 4 5 6</res>
<res>2/4/2 3 4</res>
<res>2/5/2 3 4 5</res>
<res>2/6/2 3 4 5 6</res>
<res>3/4/3 4</res>
<res>3/5/3 4 5</res>
<res>3/6/3 4 5 6</res>
EXEMPLE 2 DE FLOWER
xquery version "1.0" encoding "utf-8";
<resultat> {
for $f in doc("[Link]")/factures/facture
let $total:=sum($f/detail/produit/@montant)
where $total>90000
order by $f/@numdescending
return
<totalFacture num="{$f/@num}">{$total}</totalFacture>
}</resultat>
⚫Retourne les factures dont le total est supérieur à 90000
classées par ordre décroissant des numéros de factutue
<?xml version="1.0" encoding="UTF-8"?>
<resultat>
<totalFacture num="3">91400</totalFacture>
<totalFacture num="2">91400</totalFacture>
</resultat>
EXEMPLE 2 DE FLOWER
<resultat> {
for $f in doc("[Link]")/factures/facture let
$total:=sum($f/detail/produit/@montant)
where some $p in $f/detail/produit satisfies $p/@designation eq "PC212"
order by $f/@numdescending
return
<totalFacture num="{$f/@num}">{$total}</totalFacture>
}</resultat>
⚫Retourne le total des factures dont le total dont la désignation de
l’un des produits est « PC212 », classées par ordre décroissant des
numéros de factutue
<?xml version="1.0" encoding="UTF-8"?>
<resultat>
<totalFacture num="1">86380</totalFacture>
</resultat>
EXEMPLE 3 DE FLOWER
<resultat> {
let $xmlDoc:=doc("[Link]")
for $c in $xmlDoc//client[not(@codeClient=preceding::client/@codeClient)]
let $nbFactures:=count($xmlDoc//facture[client/@codeClient=$c/@codeClient]) let
$totalFactures:=sum(
$xmlDoc//facture[client/@codeClient=$c/@codeClient]/detail/produit/@montant
)
return
<client societe="{$c/@societe}" nbFact="{$nbFactures}"
totalFact="{$totalFactures}"/>
}</resultat>
⚫Retourne pour chaque client le nombre et le total de ses factures
<?xml version="1.0" encoding="UTF-8"?>
<resultat>
<client totalFact="86380" societe="AGFA" nbFact="1"/>
<client totalFact="182800" societe="MITAL" nbFact="2"/>
</resultat>
XQUERY : LANGAGE DE PROGRAMMATION
⚫XQuery n'est pas seulement un langage de requête "à la SQL".
⚫C'est aussi un vrai langage de programmation
fonctionnel.
⚫Il possède un certain nombre de caractéristiques qui, couplées
à quelques extensions, en font un outil intéressant pour du
développement d'applications Web.
⚫Nous allons évoquer ici quelques caractéristiques de
bases.
LES VARIABLES
⚫Nous avons déjà abordé un peu la question des
variables puisqu'elles sont utilisées dans les structures
"some" et "every", mais aussi dans la structure
"FLWOR".
⚫Cependant, XQuery propose aussi un mécanisme de
variables globales internes ou externes.
⚫Les variables internes sont déclarées avant la
requête selon la forme
◦ declare variable $v [as type] := expression_XQuery ;
◦ Le type peut être omis, il sera alors estimé en fonction de la
valeur retournée par l'expression.
LES TYPES DE VARIABLES
⚫Les types, aussi bien pour les variables que pour
les signatures des fonctions, sont ceux de XSD
avec, en plus, des types spécifiques.
⚫La figure ([Link]
functions/[Link] ). les rappelle
DÉCLARATION DE VARIABLES EXTERNES
⚫Les variables externes sont déclarées de la
manière suivante :
◦ declare variable $v [as type] external;
◦ Exemple :
◦ declare variable $v as xs:double external;
EXEMPLE DE DÉCLARATION DE VARIABLES GLOBALES
declare variable $xmlDoc:=doc("[Link]");
declare variable $max:=100000;
declare variable $clients:=
for $c in $xmlDoc//client[not(@codeClient=preceding::client/@codeClient)]
let $nbFactures:=count($xmlDoc//facture[client/@codeClient=$c/@codeClient]) let
$totalFactures:=sum(
$xmlDoc//facture[client/@codeClient=$c/@codeClient]/detail/produit/@montant)
return
<client societe="{$c/@societe}" nbFact="{$nbFactures}" totalFact="{$totalFactures}"/>; for
$c in $clients
where $c/@totalFact>$max return
$c
⚫Retourne pour chaque client le nombre et le total de ses factures dont le total est
supérieur à la variable globale max
<?xml version="1.0" encoding="UTF-8"?>
<client totalFact="182800" societe="MITAL" nbFact="2"/>
FONCTIONS ET MODULES
⚫De très nombreuses fonctions prédéfinies (
[Link] ) existent.
⚫Les fonctions sont présentées avec une signature sur
les paramètres et le retour de fonction.
⚫Pour les comprendre, il faut juste savoir que les
opérateurs sur les types signifient :
◦ "*" : une séquence qui peut être vide ;
◦ "+" : une séquence non vide ;
◦ "?" : éventuellement la séquence vide.
FONCTIONS ET MODULES
⚫Pour illustrer ces opérateurs, voici quelques exemples parmi
les très nombreuses fonctions disponibles :
◦ fn:count($arg as item()*) as xs:integer : la fonction "count"
prend en argument une séquence, éventuellement vide,
d'items et retourne un entier ;
◦ fn:string-length($arg as xs:string?) as xs:integer : la fonction
"string-length" prend en paramètre une chaîne de caractères
et retourne un entier (elle peut ne pas avoir de paramètre);
◦ fn:sum($arg as xs:anyAtomicType*) as xs:anyAtomicType" : elle
prend en argument une séquence de type de base et retourne
un type de base ;
FONCTIONS ET MODULES
⚫fn:tokenize($input as xs:string?, $pattern as xs:string) as
xs:string*" : elle prend une chaîne de caractères et un motif et
retourne une séquence de chaînes de caractères.
⚫Quelques exemples supplémentaires classés par thème :
◦ Numériques : min, max, sum, avg, count, abs, ceiling, floor,
round...
◦ Chaînes de caractères : compare, concat, substring,
string-length,starts-with, ends-width...
◦ Dates : date, current-date …
◦ Séquences : zero-or-one, one-or-more, exactly-one,
empty, exists, distinct-values, reverse,...
FONCTIONS LOCALES
⚫Ilest possible de proposer ses propres fonctions.
⚫Pour cela, dans la partie des déclarations, il suffit de décrire sa fonction de la
manière suivante :
◦ "declare function nom signature {code} ;"
◦ où :
• "nom" : soit dans un espace de noms déclaré soit préfixé par “local”
(espace de noms des fonctions pas défaut) ;
• "signature" : ( liste des paramètres, éventuellement typés ) ["as" type de
retour] ;
• "code" : n'importe quelle expression XQuery.
⚫Comme premier exemple simple, proposons une fonction permettant de construire
une séquence de nombres pairs entre 2 et une valeur donnée en paramètre. Nous
proposons ici deux versions : une avec les types explicites et une sans expliciter
les types.
EXEMPLE DE FONCTION LOCALES
xquery version "1.0" encoding "utf-8";
declare function local:liste_entier_pair($max as xs:integer) as xs:integer*
{ (2 to $max)[. mod 2 = 0]
}; Fonctionavec les
types explicites
<pair>{local:liste_entier_pair(10)}</pair>
xquery version "1.0" encoding "utf-8";
declare function local:liste_entier_pair($max ) {
(2 to $max)[. mod 2 = 0]
Fonctionnon typées
};
<pair>{local:liste_entier_pair(10)}</pair>
⚫ Retourne les nombre paires entre 0 et 10 en utilisant la fonction locale.
<?xml version="1.0" encoding="UTF-8"?>
<pair>2 4 6 8 10</pair>
EXEMPLE2 DE FONCTION LOCALES
declare function local:facturesClient($client as element(client)) as element(facture)*{
doc("[Link]")//facture[client/@codeClient=$client/@codeClient]
};
<resultat>{
let $c:=doc("[Link]")//client[@codeClient="c1"]
return local:facturesClient($c)
}</resultat>
⚫ Factures du client dont le code est « c1»
<?xml version="1.0" encoding="UTF-8"?>
<resultat>
<facture num="1" dateFacture="2006-1-1">
<client codeClient="c1" societe="AGFA"/>
<detail>
<produit designation="PC212" quantite="12" prixUnitaire="6700" montant="80400"/>
<produit designation="Imp11" quantite="3" prixUnitaire="1700" montant="5100"/>
<produit designation="Papier" quantite="22" prixUnitaire="40" montant="880"/>
</detail>
</facture>
</resultat>
LES MODULES
⚫Comme pour tout langage de programmation, il est possible de
mettre en place des bibliothèques de fonctions.
⚫En XQuery, elles s'appellent des modules.
⚫Un module consiste en un programme XQuery sans requête
principale.
⚫On y trouve donc toutes les déclarations autorisées dans un
programme XQuery.
⚫Pour caractériser un module, il suffit, en tout début,
d'indiquer son espace de noms :
◦ module namespace mon-module = 'ma:uri';
⚫Pour utiliser un module, il suffit, dans l'entête, d'indiquer
l'espace de noms et le(s) fichier(s) qui le décri(ven)t :
◦ import module namespace mon-module = 'ma:uri' at
'[Link]', '[Link]';"
EXEMPLE DE MODULE
module namespace facturation="ma:[Link]";
(:Déclaration d'une variable globale :)
declare variable $facturation:code as xs:string:="c1";
(:Déclaration d'une fonction qui retourne les nombres paires :) declare function
facturation:liste_entier_pair($max ) {
(2 to $max)[. mod 2 = 0]
};
(:Déclaration d'une fonction qui retournes les factures d'un client :) declare function
facturation:facturesClient($client as element(client)) as
element(facture)*{
doc("[Link]")//facture[client/@codeClient=$client/@codeClient]
};
⚫Module qui déclare une variable globale max et deux fonctions.
UTILISATION D’UN
MODULE
import module namespace fact="ma:[Link]" at "[Link]";
<resultat>
{
let $c:=doc("[Link]")//client[@codeClient=$fact:code]
return fact:facturesClient($c)
}
</resultat>
⚫Retourne les factures des clients « c1 ».
<?xml version="1.0" encoding="UTF-8"?>
<resultat>
<facture num="1" dateFacture="2006-1-1">
<client codeClient="c1" societe="AGFA"/>
<detail>
<produit designation="PC212" quantite="12" prixUnitaire="6700" montant="80400"/>
<produit designation="Imp11" quantite="3" prixUnitaire="1700" montant="5100"/>
<produit designation="Papier" quantite="22" prixUnitaire="40" montant="880"/>
</detail>
</facture>
</resultat>