You are on page 1of 61

Spécication d'un langage de requête par

l'exemple pour le XML (XQBE)


Jimmy GILLES
Promoteur de mémoire : Jef Wijsen
Premier rapporteur : Tom Mens
Deuxième rapporteur : Raphaël Astier

Faculté des sciences, section informatique : 2me licence

Université de Mons Hainaut


2004 - 2005
1

Remerciements
Je tiens tout d'abord à remercier monsieur Jef Wijsen pour ses nombreux
conseils ainsi que pour sa disponibilité et madame Anne-Marie Trivier pour
sa précieuse relecture. Je remercie également toutes les personnes qui, de
près ou de loin, m'ont permi de réaliser ce travail.
Table des matières

1 Introduction 6
1.1 Exemples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7

2 Spécication de XQBE 11
2.1 Dénitions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.1.1 Homomorphisme . . . . . . . . . . . . . . . . . . . . . 11
2.1.2 Xtree . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
2.1.3 Requête XQBE . . . . . . . . . . . . . . . . . . . . . . 14
2.2 Encodage de la requête et du résultat . . . . . . . . . . . . . . 15
2.2.1 Exemple d'encodage d'une requête . . . . . . . . . . . 15
2.2.2 Exemple d'encodage de la solution . . . . . . . . . . . 16

3 Traduction vers XSLT et XQuery 17


3.1 Exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
3.1.1 XSLT . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
3.1.2 XQuery . . . . . . . . . . . . . . . . . . . . . . . . . . 19
3.2 Explication du processus . . . . . . . . . . . . . . . . . . . . . 20
3.3 Suppression des doublons . . . . . . . . . . . . . . . . . . . . 21

4 Première amélioration : l'ordre 23


4.1 Solution sans ordre . . . . . . . . . . . . . . . . . . . . . . . . 24
4.2 Solution avec ordre . . . . . . . . . . . . . . . . . . . . . . . . 24
4.2.1 Explication . . . . . . . . . . . . . . . . . . . . . . . . 25
4.2.2 Nouvelle règle . . . . . . . . . . . . . . . . . . . . . . . 25
4.2.3 Remarque . . . . . . . . . . . . . . . . . . . . . . . . . 26
4.2.4 Le script XSLT . . . . . . . . . . . . . . . . . . . . . . 27
4.2.5 Le script XQuery . . . . . . . . . . . . . . . . . . . . . 28
4.3 Solution mixte . . . . . . . . . . . . . . . . . . . . . . . . . . 28
4.3.1 Explication . . . . . . . . . . . . . . . . . . . . . . . . 28
4.3.2 Nouvelle règle . . . . . . . . . . . . . . . . . . . . . . . 29
4.3.3 Requêtes en XSLT et XQuery . . . . . . . . . . . . . . 31
TABLE DES MATIÈRES 3

5 Deuxième amélioration : l'axe ancêtre-descendant 32


5.1 Fonctionnement seul . . . . . . . . . . . . . . . . . . . . . . . 32
5.1.1 Nouvelle règle . . . . . . . . . . . . . . . . . . . . . . . 35
5.2 Fonctionnement avec l'ordre . . . . . . . . . . . . . . . . . . . 35

6 Transformation d'une requête XQBE 37


6.1 Traduction vers XSLT . . . . . . . . . . . . . . . . . . . . . . 37
6.1.1 Script de base . . . . . . . . . . . . . . . . . . . . . . . 37
6.1.2 Script utilisant l'ordre . . . . . . . . . . . . . . . . . . 44
6.1.3 Le script pour l'axe ancêtre-descendant . . . . . . . . 45
6.2 Traduction vers XQuery . . . . . . . . . . . . . . . . . . . . . 46
6.2.1 Script de base . . . . . . . . . . . . . . . . . . . . . . . 46
6.2.2 Script utilisant l'ordre . . . . . . . . . . . . . . . . . . 48
6.2.3 Le script pour l'axe ancêtre-descendant . . . . . . . . 48

7 Complexité du problème 50
7.1 Problème NP-dicile . . . . . . . . . . . . . . . . . . . . . . . 50
7.1.1 Démonstration . . . . . . . . . . . . . . . . . . . . . . 53
7.2 Problème NP . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
7.3 Complexité . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54

8 Conclusion 56
8.1 Travaux futurs . . . . . . . . . . . . . . . . . . . . . . . . . . 57
8.2 Travail relatif . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
Table des gures

1.1 Document XML dbase. . . . . . . . . . . . . . . . . . . . . . . 8


1.2 Premier exemple executé sur le document dbase. . . . . . . . . 9
1.3 Second exemple executé sur le document dbase. . . . . . . . . 10

2.1 Document XML h1. . . . . . . . . . . . . . . . . . . . . . . . 11


2.2 Homorphisme de h1 vers dbase. . . . . . . . . . . . . . . . . . 12
2.3 Les Xtrees q et r formant une requête. . . . . . . . . . . . . . 14
2.4 Les deux réponses de la requête q executées sur dbase . . . . 15
2.5 Encodage d'une requête XQBE. . . . . . . . . . . . . . . . . . 16

3.1 Méthode 1 : transformation vers XSLT . . . . . . . . . . . . . 20


3.2 Méthode 2 : transformation vers XQuery . . . . . . . . . . . . 21
3.3 Requête qui donne des doublons. . . . . . . . . . . . . . . . . 22

4.1 Schéma sch2, deux homomorphismes . . . . . . . . . . . . . . 24


4.2 Requête order1 executée sur dbase. . . . . . . . . . . . . . . . 26
4.3 Requête pour la remarque . . . . . . . . . . . . . . . . . . . . 27
4.4 Requête solm1 executée sur dbase. . . . . . . . . . . . . . . . 29
4.5 Homorphisme de solm1 vers dbase . . . . . . . . . . . . . . . 30

5.1 Requête XQBE xad1 exécutée sur dbase. . . . . . . . . . . . . 33


5.2 Requête XQBE xad2 executée sur dbase. . . . . . . . . . . . . 34
5.3 Requête mélangeant l'ordre et l'axe ancêtre-descendant. . . . 36

7.1 Le graphe gA et le document XML dA. . . . . . . . . . . . . . 51


7.2 Le graphe gB et le document XML dB. . . . . . . . . . . . . . 51
7.3 Le graphe gC et le document XML dC. . . . . . . . . . . . . 52
Listings
1.1 DTD du document dbase . . . . . . . . . . . . . . . . . . . . . 7
2.1 Exemple d'encodage d'une requête . . . . . . . . . . . . . . . 15
2.2 Exemple d'encodage du résultat. . . . . . . . . . . . . . . . . 16
3.1 Transformation en XSLT . . . . . . . . . . . . . . . . . . . . . 17
3.2 Transformation en XQuery . . . . . . . . . . . . . . . . . . . . 19
4.1 Script XSLT obtenu à partir de la requête order01 . . . . . . 27
4.2 Script XQuery obtenu à partir de la requête order01 . . . . . 28
4.3 Transformation de la requête solm1 en XSLT. . . . . . . . . . 31
4.4 Transformation de la requête solm1 en XQuery. . . . . . . . . 31
5.1 Requête XQBE xad1 traduite en XSLT . . . . . . . . . . . . 33
5.2 Requête XQBE xad1 traduite en XQuery . . . . . . . . . . . 33
5.3 Requête xad2 traduite en XSLT. . . . . . . . . . . . . . . . . 34
6.1 Code source du script de base . . . . . . . . . . . . . . . . . . 37
6.2 Code source du script XSLT utilisant l'ordre . . . . . . . . . . 44
6.3 Code source du script pour l'axe ancêtre-descendant . . . . . 45
6.4 Script de base pour la transformation vers XQuery . . . . . . 46
6.5 Script pour la transformation vers XQuery utilisant l'ordre . . 48
6.6 Script pour la transformation vers XQuery utilisant l'axe ancêtre-
descendant . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
Chapitre 1

Introduction

Les bases de données relationnelles sont très utilisées dans les applica-
tions ; elles ont l'avantage d'être bien formalisées et beaucoup de recherches
ont été faites dans ce domaine.
Depuis quelques temps, le format XML[2] devient de plus en plus po-
pulaire. XML est, dans un premier temps, un langage de description de
documents. Pour chaque document créé avec XML, on obtient un arbre ; on
peut donc créer une base de données de type hiérarchique que nous appe-
lerons document XML. Alors que dans les bases de données relationnelles,
les données sont stockées dans plusieurs tables, en XML les données sont
regroupées dans un seul document. Les données peuvent être lues et éditées
par n'importe qui en utilisant un simple éditeur de texte. XML est devenu un
standard de facto pour ce qui est du transport de données, notamment pour
les applications Web comme les web-services et est de plus en plus utilisé
comme format de stockage de données.
Avec cette popularité, il a fallu proposer des outils pour récupérer des
informations d'un document XML. Le W3C a collaboré avec plusieurs entre-
prises (IBM et Microsoft en font partie) et XPath[3], XSLT[5] et XQuery[4]
ont été créés. XPath est un ensemble de règles qui permettent de se position-
ner sur un élément précis d'un document XML. XSLT permet de transformer
un document XML en un autre document (XML ou non). Quant à XQuery,
c'est un vrai langage de requêtes qui a été développé expressément dans le
but de pouvoir intérroger les bases de données XML ; il est basé sur XPath.
Pour faciliter l'usage des bases de données relationnelles, le langage QBE
(Query By Example) a été créé. Ce langage permet de questionner une base
de données sans connaître le SQL. Dans ce mémoire, nous créerons un XQBE
(XML Query By Example). L'idée de XQBE est la même que pour QBE.
En QBE, l'utilisateur doit remplir des tables vides, en XQBE, l'utilisateur
devra remplir un document vide. XQBE permettra donc à un utilisateur,
occasionnel ou non, de créer des requêtes simples qui seront executées sur
un document XML.
Le but de ce mémoire est donc, tout d'abord, de proposer un nouveau
langage qui soit simple et qui permette à l'utilisateur d'interroger des do-
Chapitre 1 : Introduction 7

cuments XML. La seconde partie sera de développer un processeur pour ce


langage.

1.1 Exemples
Nous allons illustrer XQBE en se basant sur des exemples simples. Les re-
quêtes qui seront présentées ici seront executées sur le document XML dbase
(g. 1.1). Nous n'allons pas entrer ici dans les détails purement techniques ;
ces requêtes servent de base à la compréhension de XQBE. Le document
dbase est un catalogue de livres. Pour chaque livre, on a comme informa-
tions :
 le titre du livre ;
 soit l'unique auteur du livre, soit une liste d'auteurs contenant alors,
au minimum, deux éléments ;
 une liste contenant un seul élément ou plus de sujets que le livre traite.
L'ordre indiqué ci-dessus n'est pas l'ordre respecté partout dans le document,
il se peut par exemple que l'auteur soit avant le titre du livre.

ELEMENT ∗ )>
ELEMENT
<! catalog ( book

ELEMENT
<! book ( title , slist , ( a l i s t | a u t h o r ) )>

ELEMENT
<! alist ( a u t h o r +)>

ELEMENT CDATA
<! slist ( s u b j e c t +)>

ELEMENT CDATA
<! author (# )>

ELEMENT CDATA
<! title (# )>

<! subject (# )>

Listing 1.1  DTD du document dbase

Première requête : XQBE a pour principe de base, la création de re-


quêtes de manière simple. Pour cela, les requêtes seront toutes codées en
XML, les documents XML devront être bien formés et devront respecter la
spécication XML. La gure 1.2 qui représente le premier exemple de requête
nous montre trois parties :
 la partie en haut à gauche est la requête à exécuter sur le document
XML, elle signie  donnez-moi le titre de chaque livre traitant du
XML  ;
 la partie en haut à droite est le format de sortie de chacune des solu-
tions ;
 la partie du bas est l'ensemble de toutes les réponses de la requête sur
le document dbase.
Sur cette gure, on peut remarquer que l'on a scindé la requête et le
format de sortie, ce sont deux documents XML bien distincts.
Chaque réponse correspond à un document XML bien formé, nous avons ici
deux réponses qui correspondent aux deux livres dans dbase qui traitent de
l'XML.
Chapitre 1 : Introduction 8

Fig. 1.1  Document XML dbase.


Chapitre 1 : Introduction 9

Fig. 1.2  Premier exemple executé sur le document dbase.

Deuxième requête : Pour le second exemple qui est montré par la gure
1.3, nous avons créé ce que nous appelerons une requête booléenne. C'est une
requête pour laquelle il ne peut y avoir qu'une seule réponse au maximum.
On remarque que dans ces requêtes, il n'y a pas de variable.
La requête que nous avons écrite signie :  existe-t-il un livre ayant un
titre qui soit Database ? . Étant donné que c'est bien le cas, l'unique réponse
apparait, ce qui nous montre que le livre existe bel et bien. Si le livre n'avait
pas existé, nous aurions eu une réponse vide.
Chapitre 1 : Introduction 10

Fig. 1.3  Second exemple executé sur le document dbase.


Chapitre 2

Spécification de XQBE

2.1 Dénitions
Dans un document XML, plusieurs types de n÷uds peuvent apparaître,
les n÷uds-élément, -attribut, -commentaire, -texte, -namespace, -root et -
processing instruction. Parmi cet ensemble de n÷uds, nous n'allons travailler
qu'avec les n÷uds-élément, les n÷uds-texte et le n÷ud-root.

2.1.1 Homomorphisme

Les réponses à une requête XQBE sont dénies en terme d'homomor-


phisme entre la requête et le document XML interrogé.

Exemple 1 : Les gures 2.1 et 1.1 montrent les documents XML h1 et


dbase respectivement. Un homomorphisme de h1 vers dbase est représenté
à la gure 2.2. On va donc mapper un document XML sur un autre. Par
exemple, le n÷ud-élément book de h1 est envoyé sur le n÷ud-élément book
de dbase et pas sur autre chose. On a la même chose pour les n÷uds-texte,
chacun d'eux est envoyé sur un n÷ud-texte ayant le même contenu, Jones
sur Jones , XML sur XML . Lorsque l'utilisateur va créer sa requête, il va donner

Fig. 2.1  Document XML h1.


Chapitre 2 : Spécication de XQBE 12

Fig. 2.2  Homorphisme de h1 vers dbase.


Chapitre 2 : Spécication de XQBE 13

une image de la réponse qu'il souhaite. Pour cela, il va créer un document


XML. S'il y indique que Jones est un n÷ud-texte ls d'un n÷ud-élément
auteur, il faut respecter cette image ; on ne peut donc pas prendre Jones si
son père est un n÷ud-élément acteur, la réponse ne concorderait pas avec le
choix de l'utilisateur.

Dénition 1 : Un homomorphisme d'un document XML d2 vers un docu-


ment XML d1 est un mapping h des n÷uds de d2 vers les n÷uds de d1 de
telle sorte que :

RP1 si n est un n÷ud-élément para dans d2 alors h(n) est un n÷ud-élément


para dans d1 ;
RP2 si n est un n÷ud-texte dans d2, alors h(n) est un n÷ud-texte dans d1
ayant le même contenu ;

RP3 si n est le n÷ud-root dans d2 alors h(n) est le n÷ud-root dans d1 ;


RS1 si n est un n÷ud ls de m dans d2, alors h(n) est un n÷ud ls de h(m)
dans d1.
On écrira d1  d2 si un homomorphisme de d2 vers d1 existe. Si d1  d2,
on dira aussi que d2 est homomorphique à d1.

2.1.2 Xtree

Comme nous l'avions annoncé plus tôt, les requêtes seront écrites en
XML. Les Xtree sont des chiers XML bien formés dans lesquels certains
n÷uds-texte contiennent des variables. Les variables seront notées par un #
suivi d'une lettre de l'alphabet.

Exemple 2 : La gure 2.3 montre deux Xtree, à gauche nous avons l'Xtree
q et à droite nous avons l'Xtree r. Certains n÷uds-texte contiennent des
variables, dans notre exemple, les variables utilisées sont #x et #y . Cette
requête signie :  retrouvez tous les livres qui ont le même sujet que le livre
intitulé SQL Server .

Pour parcourir les diérentes solutions, les variables seront substituées par
du texte. Pour mieux comprendre l'utilité de ces variables, reprenons le docu-
ment XML dbase. Celui-ci contient un certain nombre de n÷uds-texte. Nous
allons appliquer une évaluation θ qui va associer un texte à chaque variable,
par exemple θ(#x) = SQL et θ(#y) = Database . Nous testerons ensuite s'il
existe un homomorphisme entre ce nouveau document XML et la base de
données et si tel est le cas, l'évaluation

θ = {(#x, SQL ), (#y, Database )}

est acceptable et θ(r) sera donc une réponse à la requête. Sur la gure 2.4,
on peut voir les deux réponses à la requête.
Chapitre 2 : Spécication de XQBE 14

Fig. 2.3  Les Xtrees q et r formant une requête.

Dénition 2 : Un Xtree est un document XML bien formé dans lequel les
n÷uds-texte peuvent contenir une variable. Une variable sera notée par une
lettre de l'alphabet (ex : u, v, w, x, y, z) précédée par le caractère #.
Soit q un Xtree. Une évaluation θ de q est une fonction qui associe un
texte à chaque variable de q.
Soit θ une évaluation de q. On écrit θ(q) pour l'Xtree obtenu en substi-
tuant θ(#x) pour chaque occurence d'une variable #x dans q.

2.1.3 Requête XQBE

Lorsque l'utilisateur souhaite questionner la base de données, il utilise une


requête XQBE. Une requête XQBE contient tout d'abord un premier Xtree
qui est la requête elle-même (ex. : Xtree q ). Nous avons vu précédemment
que les requêtes sont constituées de deux parties, la deuxième partie qui
est également un Xtree va indiquer la forme que doit prendre la solution.
Dans la requête, plusieurs variables sont utilisées mais il se peut que, parmi
elles, seul le contenu de quelques-unes sera réutilisé dans les réponses ; nous
utiliserons alors uniquement ces variables dans le deuxième Xtree. C'est pour
cette raison que nous avons séparé la requête et le format de sortie.

Exemple 3 : Prenons q notre premier Xtree, celui qui sera utilisé comme
requête. Pour le deuxième Xtree, celui qui indiquera la forme des solutions,
nous allons prendre r. Étant donné que seul le titre du livre nous intéresse,
nous n'avons que la variable #y qui apparait dans r. Il faut également noter
que le n÷ud parent de #y est intitulé titre et non title, cela nous est tout à
fait permis.

θ dénie par θ(#x) = SQL et θ(#y) = Database ,


Si nous prenons l'évaluation
alors θ(q) est homomorphique à dbase ; en appliquant cette évaluation à l'X-
tree r, on obtient une première réponse. Si on procède de la sorte en prenant
une autre évaluation θ0 dénie par θ0 (#x) = SQL et θ0 (#y) = SQL Server ,
on obtient la deuxième réponse. Pour cet exemple, seules deux évaluations
Chapitre 2 : Spécication de XQBE 15

Fig. 2.4  Les deux réponses de la requête q executées sur dbase

sont acceptables. L'ensemble de toutes les réponses est représenté à la gure


2.4.

Dénition 3 : Une requête XQBE est une paire Q = (q, r) où q et r sont


des Xtree de sorte que chaque variable qui apparait dans r apparait aussi
dans q.
L'xtree q sera appelé le corps de la requête tandis que r sera appelé la tête
de la requête.
Soit dbase un document XML, soit Q = (q, r) une requête XQBE. Si θ
q de sorte que dbase  θ(q), alors θ(r) est une réponse
est une évaluation de
pour Q dbase. On écrit Q(dbase) pour l'ensemble de toutes les réponses
sur
de Q sur dbase.

2.2 Encodage de la requête et du résultat


Nous avons déni ce qu'est une requête XQBE, il est maintenant néces-
saire de trouver un encodage pour ces requêtes. Une requête XQBE Q(q, r)
peut être encodée dans un seul document XML. Le Xtree q peut être déli-
mité par les balises <body> </body> et r par <head> </head>. Les balises
<xqbe> et </xqbe> formeront le n÷ud ls du n÷ud-root. Nous aurons de
cette manière un document XML bien formé.

2.2.1 Exemple d'encodage d'une requête

Le listing 2.1 est un exemple d'encodage de la requête. La partie q (g.


2.3) se trouve entre les balises <body> et </body>. Tandis que la partie r
se trouve entre les balises <head> et </head>. Le tout se trouvant entre les
balises <xqbe> et </xqbe>. La gure 2.5 est la représentation graphique de
ce document.

<? xml version =" 1 . 0 " standalone =" no " ?>

<x q b e>

<body>

< c a t a l o g>

<b o o k>

< t i t l e >SQL S e r v e r</ t i t l e >


Chapitre 2 : Spécication de XQBE 16

Fig. 2.5  Encodage d'une requête XQBE.

< s l i s t>

< s u b j e c t>#x</ s u b j e c t>

</ s l i s t >

</ b o o k>

<b o o k>

< t i t l e >#y</ t i t l e >

< s l i s t>

< s u b j e c t>#x</ s u b j e c t>

</ s l i s t >

</ b o o k>

</ c a t a l o g>

</ body>

<h e a d>

< t i t l e >#y</ t i t l e >

</ h e a d>

</ x q b e>

Listing 2.1  Exemple d'encodage d'une requête

2.2.2 Exemple d'encodage de la solution

Toutes les réponses seront rassemblées dans un seul document XML.


L'Xtree r est le format de sortie que nous avons choisi pour les réponses de
la requête q. Pour chacune d'elle, il ne faut récupérer que le titre du livre. Le
listing 2.2 est un exemple d'encodage du résultat. Nous avons deux réponses ;
chaque titre de livre est entouré des balises <titre> et </titre>. Pour que
le document XML soit bien formé, il est nécessaire de regrouper toutes les
réponses entre les balises <xqbe> et </xqbe>.

<? xml version =" 1 . 0 " e n c o d i n g=" u t f −8" ?>


<x q b e>

< t i t l e >SQL S e r v e r</ t i t l e >

< t i t l e >D a t a b a s e</ t i t l e >

</ x q b e>

Listing 2.2  Exemple d'encodage du résultat.


Chapitre 3

Traduction vers XSLT et


XQuery

3.1 Exemple
Nous allons maintenant voir le côté pratique de XQBE. Nous allons donc
voir un exemple concret de la requête au résultat tout en expliquant les
diérentes étapes.
Toute requête XQBE peut être exprimée comme une transformation
XSLT ou comme une requête XQuery.
Prenons la requête XQBE Q = (q, r) de la gure 2.3. Cette requête sera
exécutée sur le document dbase. Le résultat est connu et a été montré à la
gure 2.4.

3.1.1 XSLT

Nous allons d'abord exprimer notre requête en XSLT, le listing 3.1 montre
comment une telle requête Q peut être vue en XSLT.

1<x s l : s t y l e s h e e t version =" 1 . 0 7 " x m l n s : x s l=" h t t p : / /www . w3 . o r g / 1 9 9 9 /XSL/ T r a n s f o r m ">

2 < x s l : t e m p l a t e match=" / ">

3 <x q b e>

4 < x s l : f o r −e a c h s e l e c t =" / / t e x t ( ) ">

5 < x s l : v a r i a b l e name=" x " s e l e c t =" . " />

6 <x s l : i f t e s t =" n o t ( p r e c e d i n g : : t e x t ( ) [ . = $ x ] ) ">

7 < x s l : f o r −e a c h s e l e c t =" / / t e x t ( ) ">

8 < x s l : v a r i a b l e name=" y " s e l e c t =" . " />

9 <x s l : i f t e s t =" n o t ( p r e c e d i n g : : t e x t ( ) [ . = $ y ] ) ">

10 <x s l : i f t e s t =" / c a t a l o g [ b o o k [ t i t l e [ . = ' SQL S e r v e r ' ] ]

11 [ s l i s t [ subject [.=$ x ] ] ] ]

12 [ book [ t i t l e [ . = $ y ] ]

13 [ s l i s t [ s u b j e c t [ . = $ x ] ] ] ] ">

14 < t i t r e>

15 < x s l : v a l u e −o f s e l e c t = ' $ y ' />

16 </ t i t r e >

17 </ x s l : i f >

18 </ x s l : i f >

19 </ x s l : f o r −e a c h >

20 </ x s l : i f >
Chapitre 3 : Traduction vers XSLT et XQuery 18

21 </ x s l : f o r −e a c h >

22 </ x q b e>

23 </ x s l : t e m p l a t e>

24 </ x s l : s t y l e s h e e t >

Listing 3.1  Transformation en XSLT

Nous allons étudier le fonctionnement de l'algorithme à partir de la re-


quête XSLT. Celle-ci ne contient qu'un seul template, on peut comparer cette
requête à une simple fonction qui n'en appelle aucune autre et qui travaille
sur tout le document XML. Nous avons ensuite la balise <xqbe>, c'est elle
qui englobe toutes les réponses pour s'assurer que le chier résultat soit un
document XML bien formé.
De la ligne 4 à la ligne 9, nous allons parcourir toutes les évaluations
possibles. Les lignes 10 à 13 auront pour rôle de tester si oui ou non, les dif-
férentes évaluations permettent d'obtenir un homomorphisme entre le corps
de la requête et le document XML et donc une réponse. Enn, de la ligne
14 à la ligne 16, nous avons la partie qui correspond à la tête de Q, c'est-
à-dire la partie qui sera écrite dans le chier résultat. Dans r, nous avions
demandé que la valeur de la variable #y soit placée entre les balises <titre>
et </titre>, c'est bien ce que nous avons ici. Le reste des lignes ne sont que
les balises fermantes car un chier XSLT est avant tout un chier XML et
doit donc respecter les mêmes règles.
Les lignes 4 à 6 et les lignes 7 à 9 sont presque identiques, seule la variable
utilisée dière ; dans le premier bloc, nous utilisons la variable x et dans le se-
cond, la variable y . Ces deux variables correspondent aux deux variables uti-
lisées dans le corps de la requête Q. Ces deux blocs vont permettre aux deux
variables de prendre chacune des valeurs se trouvant dans les n÷uds-texte
du document XML et qui sont{Jean, Smith, SQL Server, SQL, Jones,
Database, XML, SQL, XML-RPC, Smith, Jean, XML, RPC} . La ligne 4 (res-
pectivement 7) est donc la boucle qui parcourt chaque n÷ud-texte, la ligne
5 (respectivement 8) assigne à x (respectivement y) la valeur du n÷ud-texte
courant. Les lignes 6 et 9 sont un peu spéciales, nous les expliquerons un peu
plus tard.
Nous arrivons ensuite au bloc composé des lignes 10 à 13. Ces lignes qui
ne forment qu'un if sont les lignes qui vont tester si pour les valeurs assignées
à x et y, le corps de la requête devient homomorphique au document XML.
Si c'est la cas, on a trouvé une réponse à la requête.
Revenons maintenant à la ligne 6, pour la ligne 9 les explications sont
identiques. Cette ligne va s'assurer que la variable x ne prend pas deux fois
la même valeur. Étant donné que chaque réponse correspond à une évalua-
tion θ, tester deux fois la même évaluation risque de créer des doublons
dans le résultat. Par exemple, supposons que la variable y prenne la valeur
Database . La variable x va parcourir tous les n÷uds-texte de dbase. Or,
dans ce document, il existe plusieurs n÷uds-texte ayant la même valeur, par
Chapitre 3 : Traduction vers XSLT et XQuery 19

exemple SQL . Si nous n'avions pas placé de test sur les variables, nous au-
rions testé deux fois l'évaluation θ = {(#x, SQL ), (#y, Database )} et nous
aurions eu un doublon car θ(q) est bien homomorphique à dbase ; le problème
des doublons sera étudié en détail à la section 3.3.

3.1.2 XQuery

Nous allons maintenant exprimer notre requête en XQuery. Le listing


3.2 nous montre comment la requête Q peut être vue en tant que requête
XQuery. Contrairement à XSLT, c'est dans la source de la requête XQuery
que l'on indique sur quel chier devra être executée la requête. Pour cela, la
ligne let $doc := doc(dbase.xml) qui indique que l'on va travailler sur
le chier dbase.xml doit être modiée si on travaille sur un autre chier.

1 <x q b e>
2{
3 l e t $ doc : = d o c ( " d b a s e . xml " )

4
5 f o r $x i n d i s t i n c t −v a l u e s ( $ d o c / / t e x t ( ) )

6 f o r $y i n d i s t i n c t −v a l u e s ( $ d o c / / t e x t ( ) )

7 where

8 $ d o c / c a t a l o g [ b o o k [ t i t l e [ . = ' SQL S e r v e r ' ] ]

9 [ s l i s t [ subject [.=$ x ] ] ] ]

10 [ book [ t i t l e [ . = $ y ] ]

11 [ s l i s t [ subject [.=$ x ] ] ] ]

12 return

13 < t i t r e >{ $ y }</ t i t r e >

14 }
15 </ x q b e>

Listing 3.2  Transformation en XQuery

A la première ligne de la requête, nous retrouvons la balise <xqbe> que


nous avions déjà trouvé dans le script XSLT et qui va englober toutes les
solutions.
Nous avons ensuite les lignes 5 et 6 qui représentent la partie qui va par-
courir les possibilités de réponse. On a donc deux boucles qui vont parcourir
les n÷uds-texte du document. Le mot-clé distinct-values représente le
test qui s'assure que x ne parcourra qu'une seule fois chaque valeur.
Le bloc formé des lignes 7 à 11 est le test d'homomorphisme, le test est
identique au test se trouvant dans la requête XSLT. Et enn, nous avons les
lignes 12 et 13 qui indiquent le format de sortie des réponses.

L'utilisateur ne doit connaître ni XSLT ni XQuery pour recréer ces re-


quêtes ; la traduction de la requête XQBE en transformation XSLT ou en
requête XQuery peut être totalement automatisée. Il existe en eet un script
XSLT qui se charge de cette traduction. Les diérents scripts seront étudiés
en détail au chapitre 6.
Chapitre 3 : Traduction vers XSLT et XQuery 20

Fig. 3.1  Méthode 1 : transformation vers XSLT

3.2 Explication du processus


Nous venons d'étudier un exemple de requête XSLT et XQuery. Nous
allons maintenant expliquer les diérentes étapes du processus. Les gures
3.1 et 3.2 montrent les processus si on opte pour une traduction vers XSLT
ou vers XQuery.
Comme nous l'avons précisé dans la section précédente, la traduction
est automatisée ; nous fournissons à l'utilisateur le script qui s'en chargera.
L'utilisateur n'a donc besoin que de deux chiers :
 son document XML ;
 sa requête XQBE.
La première étape consiste, grâce au script XSLT : XMOTEUR que nous
étudierons au chapitre 6, à créer une requête XSLT ou XQuery. Ce ne sont
pas les deux seules possibilités, cependant, nous n'avons exploré que ces deux-
là, on aurait pu utiliser SAX, DOM ou encore implémenter le tout dans un
programme C.
Une fois que nous avons notre requête XSLT ou XQuery, il ne reste
plus qu'à l'exécuter sur le document XML. Un chier résultat contenant
l'ensemble de toutes les réponses est alors créé.
Du point de vue de l'utilisateur nal, ces deux étapes peuvent être assez
 ennuyantes  à utiliser. Pour éviter ce problème, on pourrait créer un script
adapté au système d'exploitation (en DOS pour Windows, en Bash pour Li-
nux) qui exécuterait toutes les commandes nécessaires pour obtenir le chier
avec les réponses. Mais du point de vue du développeur, le script obtenu
grâce à XMOTEUR est intéressant car il permet de bien en comprendre le
fonctionnement interne.
Chapitre 3 : Traduction vers XSLT et XQuery 21

Fig. 3.2  Méthode 2 : transformation vers XQuery

3.3 Suppression des doublons


Qu'est-ce qu'un doublon ? Il est dicile de répondre à cette question.
Revenons à la requête XSLT montrée à la gure 3.1, nous avions dit que tester
deux fois la même évaluation pouvait provoquer des doublons. Cependant,
ces évaluations identiques ont été créées à partir de n÷uds-texte diérents
mais ayant un même contenu. Nous avons donc deux fois la même réponse
qui apparait, comment devons-nous interpréter ces deux réponses ? Faut-il
considérer ces deux réponses comme étant des doublons ou bien faut-il les
considérer comme étant diérentes ?
Continuons par la requête montrée à la gure 3.3. Nous voulons récupérer
la liste des sujets des livres ayant un titre. Dans la tête de la requête, nous
ne plaçons que la variable #y car c'est la seule qui nous intéresse.
Cette requête est executée sur le document dbase. Cinq évaluations nous
permettent d'obtenir une réponse, en voici la liste :
 θ1 = {(#x, SQL Server ), (#y, SQL )}
 θ2 = {(#x, Database ), (#y, SQL )}
 θ3 = {(#x, Database ), (#y, XML )}
 θ4 = {(#x, XML-RPC ), (#y, XML )}
 θ5 = {(#x, XML-RPC ), (#y, RPC )}
Sur la gure 3.3 on voit pourtant que dans les 5 réponses, nous en avons
plusieurs qui sont identiques. On peut donc en déduire que le fait de ne
jamais tester une même évaluation plusieurs fois ne garantisse pas l'absence
de plusieurs réponses identiques. La manière d'écrire la requête a donc de
l'importance ; dans notre exemple, on aurait pu éviter de placer la variable
#x. La variable #y aurait alors parcouru les n÷uds {SQL , XML , RPC } et
Chapitre 3 : Traduction vers XSLT et XQuery 22

Fig. 3.3  Requête qui donne des doublons.

nous n'aurions pas eu ce problème. Devons-nous dans ce cas-ci considérer


ces réponses comme étant des doublons ?
On voit donc qu'il est dicile de savoir ce qu'est un doublon. C'est un
sujet assez compliqué qui peut prendre beaucoup de temps pour être résolu.
Dans le cadre de ce rapport, nous n'allons pas explorer ce problème plus
longtemps. Pour la suite de ce rapport, nous allons simplement continuer
avec ce que nous avons déjà utilisé, c'est-à-dire ne pas tester deux fois la
même évaluation.
Chapitre 4

Première amélioration :
l'ordre

Lorsque les bases de données relationnelles ont été développées, l'ordre


des tuples n'avait pas d'importance. Si on a deux tuples, aucun des deux n'est
premier. Seul le résultat peut être ordonné selon un critère explicitement
choisi par l'utilisateur.
A l'inverse, lorsque XML a été développé, il l'a été en gardant à l'esprit
que les éléments soient stockés d'une manière ordonnée. C'est à dire que si
l'on prend deux n÷uds frères, il y en a un des deux qui est premier tandis
que l'autre est deuxième. Le premier étant celui qui apparait en premier dans
le texte.
Pour que cela soit plus clair, si on reprend le document XML dbase, le
n÷ud-élément catalog a trois n÷uds ls book ; parmis ces trois n÷uds, celui
dont le titre estSQL Serveur est le premier, le deuxième est celui dont le
titre est Database et enn le troisième est celui dont le titre est XML-RPC . Il
y a donc vraiment un ordre dans la manière d'écrire le document XML. Si
on avait inversé deux livres, on aurait obtenu un autre document.
Attention, il faut bien distinguer l'ordre du document XML et l'ordre
dans lequel les réponses seront données. Pour le résultat, les réponses appa-
raîtront dans l'ordre dans lequel elle seront trouvées. Étant donné que les
variables parcourent les n÷uds-texte du début à la n du document, les ré-
ponses auront donc un lien avec ce parcours. Le problème qui nous préoccupe
est de savoir si oui ou non, l'ordre dans lequel le document à été créé doit
avoir de l'importance.
Reprenons notre document XML dbase. On pourrait penser que l'utilisa-
teur a placé les livres en fonction de la date d'achat de ceux-ci. Son premier
achat a donc été celui intitulé SQL Server. Il peut donc se servir de cet ordre
pour savoir quels sont les livres achetés après un livre donné ; en regardant
le document XML, on obtient la réponse facilement. Cependant, avec ce que
nous avons formalisé jusqu'a présent, il nous est impossible de récupérer le
titre du livre acheté après le livre intitulé Database . Pour cela, nous chan-
gerons la syntaxe des requêtes, nous étudierons cela à la section 4.2.
Chapitre 4 : Première amélioration : l'ordre 24

Fig. 4.1  Schéma sch2, deux homomorphismes

L'ordre n'est peut-être pas toujours important, si on demande tous les


auteurs qui ont écrit sur le même sujet que Jones, que ces auteurs soient
placés avant ou après Jones ne nous importe pas, ils doivent apparaître dans
le résultat.

4.1 Solution sans ordre


C'est la solution que nous avons utilisée jusqu'à présent. En ne changeant
rien à son document XML, l'utilisateur ne pourra pas utiliser XQBE pour
retrouver les livres qui suivent/précèdent un livre donné.
Les scripts XSLT et XQuery ont déjà été vus en détail à la page 17, nous
ne reviendrons donc pas sur cette solution.

4.2 Solution avec ordre


La solution que nous allons proposer ici est de toujours prendre en compte
l'ordre des éléments d'un document. Prenons le schéma sch2 (g 4.1), il nous
montre deux homomorphismes entre un Xtree et un document qui est un clas-
sement de plusieurs personnes (le critère de classement n'a pas d'importance
ici). Dans la requête, le n÷ud-élément nom qui a le n÷ud ls John doit
obligatoirement être mappé sur le troisième n÷ud-élément nom du docu-
ment XML pour respecter les règles d'homomorphisme. Ensuite, nous avons
le deuxième n÷ud-élément nom dont le n÷ud ls contient la variable #x.
Cette variable peut prendre 5 valeurs diérentes mais nous n'allons en voir
que deux car les autres cas peuvent être ramenés à l'un de ces deux choix. La
Chapitre 4 : Première amélioration : l'ordre 25

variable va donc prendre soit la valeur Fred , soit la valeur Julie . Nous avons
donc deux mapping diérents. Mais dans le premier cas, θ(#x) = Fred ,
l'ordre des n÷uds-élément n'est pas respecté ; on le voit car les èches se
croisent.
Pour le n÷ud Pierre , l'idée est la même que pour Julie . Bien entendu,
ce sont deux n÷uds diérents qui donneront deux réponses diérentes mais
que le n÷ud soit le premier following-sibling ou un autre n'a pas d'impor-
tance, il suit le n÷ud John , il n'y a donc pas de problème. Pour Ed , nous
l'avons aussi omis car comme il précède John il ne sera pas repris dans la
réponse, c'est la même idée que pour le n÷ud Fred .
Qu'entendons-nous par :  les èches se croisent  ? Prenons deux n÷uds
frères a et b dans un document XML avec a qui précède b. Le n÷ud a sera
mappé sur un n÷ud am d'un autre document XML et b sur un n÷ud bm
avec am et bm qui sont frères. Si bm précède am alors, graphiquement, on
dira que les èches qui représentent les mapping se croisent.

4.2.1 Explication

Maintenant supposons que l'ordre soit implicite. Dans la requête, pre-


nons n, nom et m, le deuxième. Comme l'ordre
le premier n÷ud-élément
doit être respecté et que n est preceding-sibling de m, m n'a pas d'autre
choix que d'être mappé sur un des deux derniers n÷uds-élément nom (n doit
obligatoirement être mappé sur celui du milieu) et h(n) est bien preceding-
sibling de h(m). Le premier homomorphisme ne peut donc pas être repris car
h(n) preceding-sibling h(m) ne serait pas respecté. Ainsi, le fait d'imposer
l'ordre parmi un ensemble de frères se voit graphiquement car les èches ne
se croisent pas.

Exemple 4 : Voyons le fonctionnement avec la requête de la gure 4.2. On


souhaite retrouver tous les livres qui ont été achetés après celui de Jones.
Nous exécuterons cette requête sur notre document XML dbase (g. 1.1).
En regardant dans le document, la réponse est facile à trouver, il n'y en a
qu'un : XML-RPC.
Dans la requête, il n'y a que les n÷uds-élément book qui sont frères. Ce sont
donc les seuls qui seront ordonnés. Cependant, le n÷ud author étant ls du
premier book et title ls du deuxième book, implicitement ils seront ordonnés.
C'est-à-dire que title sera automatiquement un following de author.

4.2.2 Nouvelle règle

Nous allons  redénir  ce qu'est un homomorphisme en utilisant une


règle supplémentaire. Reprenons l'ensemble des règles suivantes qui ont été
dénies dans la dénition d'homomorphisme à la page 13 : {RP1, RP2, RP3,
RS1} auquel nous ajoutons la règle dénie ci-après.
Chapitre 4 : Première amélioration : l'ordre 26

Fig. 4.2  Requête order1 executée sur dbase.

RS2 : si n est un preceding-sibling de m dans d2 alors h(n) est un preceding-


sibling de h(m) dans d1.

Attention, dire que n est preceding-sibling de m implique que n 6= m.


Cette nouvelle dénition impose le fait que l'ordre soit respecté partout.

4.2.3 Remarque

L'utilisation de l'ordre nous permet de faire une remarque intéressante.


Revenons-en à la gure 4.1. Sur le document XML, nous allons exécuter la
requête montrée à la gure 4.3. Cette requête signie :  donnez-moi la liste
de tous les noms sauf les deux premiers . Une autre requête possible aurait
été :  donnez-moi la liste de tous les noms sauf les deux derniers  en plaçant
deux n÷uds nom à la n au lieu de les placer au début comme sur la gure.
A l'inverse, il n'est pas possible de récupérer uniquement les deux pre-
miers si on ne connait pas le nombre total de n÷uds nom. Intuitivement,
cela vient du fait qu'en XQBE, on peut indiquer ce que l'on souhaite mais il
nous est impossible de dire ce que nous ne voulons pas. Si on retourne sur la
gure 4.3, on demande qu'il y ait au moins deux n÷uds nom avant celui qui
nous intéresse, c'est à dire celui avec la variable #x. C'est pour cela que l'on
arrive à récupérer tous les n÷uds sauf les deux premiers. Par contre, si nous
avions voulu récupérer uniquement le dernier, nous aurions dû dire qu'après
le n÷ud qui nous intéresse, aucun autre n÷ud ne doit apparaître et cela est
impossible avec XQBE.
Chapitre 4 : Première amélioration : l'ordre 27

Fig. 4.3  Requête pour la remarque

4.2.4 Le script XSLT

Si nous transformons la requête de la gure 4.2, nous obtenons le listing


4.1.

1<x s l : s t y l e s h e e t version =" 1 . 0 7 ">

2 < x s l : t e m p l a t e match=" / ">

3 <x q b e>

4 < x s l : f o r −e a c h s e l e c t =" / / t e x t ( ) ">

5 < x s l : v a r i a b l e name=" x " s e l e c t =" . " />

6 <x s l : i f t e s t =" n o t ( p r e c e d i n g : : t e x t ( ) [ . = $ x ] ) ">

7 <x s l : i f t e s t =" / c a t a l o g [ b o o k [ a u t h o r [ . = ' J o n e s ' ] ]

8 / f o l l o w i n g −s i b l i n g : : b o o k [ t i t l e [ . = $ x ] ] ] ">

9 < l i v r e>

10 < x s l : v a l u e −o f s e l e c t =" $ x " />

11 </ l i v r e >

12 </ x s l : i f >

13 </ x s l : i f >

14 </ x s l : f o r −e a c h>

15 </ x q b e>

16 </ x s l : t e m p l a t e>

17 </ x s l : s t y l e s h e e t >

Listing 4.1  Script XSLT obtenu à partir de la requête order01

Nous avons déjà étudié en détail un script XSLT. Mais ce nouveau script
n'est pas identique. Les diérences interviennent au niveau du test if des
lignes 7 et 8. On utilise maintenant le mot-clé following-sibling. Ce mot-clé
doit être placé entre deux n÷uds frères.
Dans notre exemple, les n÷uds book sont frères, on place donc un following-
sibling entre eux. Même si ici il n'y a qu'une occurence de ce mot-clé, on peut
l'utiliser sans aucune limite, tout dépend de la requête.
Chapitre 4 : Première amélioration : l'ordre 28

4.2.5 Le script XQuery

1 <x q b e>
2{
3 l e t $ doc : = d o c ( " d a t a b a s e . xml " )

4
5 f o r $x i n d i s t i n c t −v a l u e s ( $ d o c / / t e x t ( ) )

6 where

7 $ doc / c a t a l o g [ book

8 [ author [.= ' Jones ' ] ]

9 / f o l l o w i n g −s i b l i n g : : b o o k [ t i t l e [.=$ x ] ] ]

10 return

11 < l i v r e >{ $ x }</ l i v r e >

12 }
13 </ x q b e>

Listing 4.2  Script XQuery obtenu à partir de la requête order01

Attention, dans ce script, nous utilisons le mot-clé following-sibling


mais cet axe n'est pas implémenté dans tous les logiciels de traitement de
XQuery. En eet, la spécication n'en oblige pas l'implémentation.

4.3 Solution mixte


La solution qui semble la plus adaptée est de laisser le choix à l'utilisateur
s'il souhaite utiliser l'ordre ou non. En plaçant un attribut order sur le n÷ud
racine, il aurait cette exibilité. On placerait l'attribut sur la valeur yes si on
souhaite l'ordre et sur no dans le cas contraire. L'attribut permet de choisir
uniquement une des deux solutions précédentes.
Proposons une solution encore plus exible, laissons le choix à l'utilisateur
de décider à chaque n÷ud si l'ordre devra être pris en compte pour les ls
de ce n÷ud. Au lieu d'utiliser l'attribut order uniquement à la racine, on
va l'utiliser sur chaque n÷ud-élément. Pour éviter que le système soit trop
lourd à utiliser, la valeur par défaut de l'attribut sera no ; on peut donc se
passer de placer l'attribut order si la valeur est no.

4.3.1 Explication

A chaque n÷ud n, l'utilisateur devra choisir si l'ordre des n÷uds ls de


n doit être pris en compte ; si tel est le cas, il devra alors ajouter l'attribut
order avec la valeur yes.
La solution précédente qui consistait à appliquer l'ordre partout est en
fait un cas particulier de cette solution-ci dans lequel on a placé l'attribut
order avec la valeur yes à chaque n÷ud-élément de la requête. Dans la même
idée, la solution sans ordre (voir section 4.1) est un cas particulier dans lequel
aucun n÷ud n'a l'attribut order avec la valeur yes.
Chapitre 4 : Première amélioration : l'ordre 29

Fig. 4.4  Requête solm1 executée sur dbase.

Exemple 5 : Prenons la requête solm1 (g. 4.4), l'utilisateur a ajouté un


attribut order avec la valeur yes sur le n÷ud alist. Ce qui veut dire qu'il sou-
haite que l'ordre des auteurs soit respecté ; la requête signie donc  donnez-
moi les titres des livres dont l'auteur Smith se trouve avant l'auteur Jean .
Dans notre document dbase, cela correspond au troisième livre qui est donc
XML-RPC .
On peut également remarquer que le fait d'avoir inversé les deux n÷uds alist
et title n'inuence en rien le résultat, étant donné que le n÷ud book n'a
pas d'attribut order ; les n÷uds alist et title seront donc convenablement
mappés.

Dans l'homomorphisme (g. 4.5), on remarque bien que l'ordre des au-
teurs est respecté ; par contre dans la requête, on a le n÷ud alist qui apparait
avant le n÷ud title et pourtant cela ne pose aucun problème car l'ordre ne
doit pas être respecté à ce niveau là.
Le document dbase contient un autre livre avec les mêmes auteurs, ce-
pendant, pour ce livre, le premier auteur est Jean alors que le deuxième est
Smith . L'ordre des auteurs n'étant pas celui souhaité par l'utilisateur, ce
livre n'est pas pris comme solution.

4.3.2 Nouvelle règle

Ici également, nous allons  redénir  ce qu'est un homomorphisme.


Reprenons l'ensemble des règles suivantes dénies à la page 13 : {RP1, RP2,
Chapitre 4 : Première amélioration : l'ordre 30

Fig. 4.5  Homorphisme de solm1 vers dbase


Chapitre 4 : Première amélioration : l'ordre 31

RP3, RS1} auquel nous ajoutons la règle dénie ci-après.

RS3 : si n est un preceding-sibling de m avec le parent commun p qui a un


attribut order avec la valeur  yes , alors h(n) est un preceding-sibling
de h(m).

4.3.3 Requêtes en XSLT et XQuery

1<x s l : s t y l e s h e e t version =" 1 . 0 7 " x m l n s : x s l=" h t t p : / /www . w3 . o r g / 1 9 9 9 /XSL/ T r a n s f o r m ">

2 < x s l : t e m p l a t e match=" / ">

3 <x q b e>

4 < x s l : f o r −e a c h s e l e c t =" / / t e x t ( ) ">

5 < x s l : v a r i a b l e name=" x " s e l e c t =" . " />

6 <x s l : i f t e s t =" n o t ( p r e c e d i n g : : t e x t ( ) [ . = $ x ] ) ">

7 <x s l : i f t e s t =" / c a t a l o g [ b o o k

8 [ a l i s t [ a u t h o r [ . = ' Smith ' ]

9 / f o l l o w i n g −s i b l i n g : : a u t h o r [ . = ' Jean ' ] ] ]

10 [ title [ . = $ x ] ] ] ">

11 < t i t l e>

12 < x s l : v a l u e −o f s e l e c t = ' $ x ' />

13 </ t i t l e >

14 </ x s l : i f >

15 </ x s l : i f >

16 </ x s l : f o r −e a c h >

17 </ x q b e>

18 </ x s l : t e m p l a t e>

19 </ x s l : s t y l e s h e e t >

Listing 4.3  Transformation de la requête solm1 en XSLT.

Le listing 4.3 est le script que l'on obtient en transformant la requête


solm1 en XSLT. Dans la requête, nous avions placé l'attribut order sur le
n÷ud alist, nous avons donc un preceding-sibling entre les deux author. Par
contre, entre les n÷uds frères alist et title, il n'y a pas de preceding-sibling.

1 <x q b e>
2{
3 l e t $ doc : = d o c ( " d b a s e . xml " )

4
5 f o r $x i n d i s t i n c t −v a l u e s ( $ d o c / / t e x t ( ) )

6 where

7 $ doc / c a t a l o g [ book

8 [ a l i s t [ a u t h o r [ . = ' Smith ' ]

9 / f o l l o w i n g −s i b l i n g : : a u t h o r [ . = ' Jean ' ] ] ]

10 [ t i t l e [.=$ x ] ] ]

11 return

12 < t i t l e >{ $ x }</ t i t l e >

13 }
14 </ x q b e>

Listing 4.4  Transformation de la requête solm1 en XQuery.


Chapitre 5

Deuxième amélioration :
l'axe ancêtre-descendant

Nous allons maintenant voir ce que nous appellerons  l'axe ancêtre-


descendant . Nous commencerons par voir si son utilisation est possible et
quelles en sont les conséquences. Ensuite, nous verrons s'il est possible de
mélanger les deux améliorations, l'ordre et l'axe ancêtre-descendant. Dans
cette partie, la syntaxe des requêtes ne changera pas mais la sémantique
changera. Pour la majorité des requêtes que nous pouvons écrire, le résultat
ne sera pas le même que précédemment.

5.1 Fonctionnement seul


Jusqu'à présent, dans les requêtes XQBE l'utilisateur devait toujours
écrire le chemin absolu. C'est-à-dire que s'il ne s'intéressait qu'à la liste de
tous les titres présents dans le catalogue, il devait, dans sa requête, utiliser le
chemin /catalog/book/title, cela pour respecter la règle RS1. Si le n÷ud title
avait été à un plus bas niveau de profondeur, il aurait fallu ajouter encore plus
de n÷uds intermédiaires. En plus de cela, il doit connaître convenablement
la structure complète du document XML pour écrire des requêtes correctes.
Nous allons tenter de rendre cet aspect des requêtes moins compliqué.
L'idée est de remplacer l'axe parent-enfant par l'axe ancêtre-descendant, ainsi
si on est intéressé par la liste des titres, on peut raccourcir le chemin en ne
plaçant que le n÷ud title.

Exemple 6 : La première requête ad1 (g. 5.1) qui signie :  donnez-moi


la liste de tous les titres présents dans le document  et que nous exécuterons
sur dbase est très facile à écrire, seuls deux n÷uds sont nécessaires :
 un n÷ud-élément pour le chemin ;
 un n÷ud-texte pour la variable.
Le fonctionnement est le suivant : on substitue, comme avant, la ou les
variables de la requête. Mais la suite dière, ici, on va simplement demander
s'il existe, dans le document, un n÷ud title qui est descendant du n÷ud-root
Chapitre 5 : Deuxième amélioration : l'axe ancêtre-descendant 33

Fig. 5.1  Requête XQBE xad1 exécutée sur dbase.

et qui a un descendant texte avec la valeur de la substitution.


Il y a trois solutions valables, ce sont les trois livres du document. Bien
entendu, cette requête est assez générale, si dans le document XML il y
avait eu un n÷ud movie avec un n÷ud ls title, le titre du lm aurait été
repris dans le résultat. Le listing 5.1 est la traduction de la requête xad1 en
XSLT.

<x s l : s t y l e s h e e t version =" 1 . 0 7 " x m l n s : x s l=" h t t p : / /www . w3 . o r g / 1 9 9 9 /XSL/ T r a n s f o r m ">

<x s l : t e m p l a t e match=" / ">

<x q b e>

<x s l : f o r −e a c h s e l e c t =" / / t e x t ( ) ">

<x s l : v a r i a b l e name=" x " s e l e c t =" . " />

<x s l : i f t e s t =" n o t ( p r e c e d i n g : : t e x t ( ) [ . = $ x ] ) ">

<x s l : i f t e s t =" / / t i t l e [ d e s c e n d a n t : : t e x t ( ) [ . = $ x ] ] ">

< t i t l e>

<x s l : v a l u e −o f s e l e c t = ' $ x ' />

</ t i t l e >

</ x s l : i f >

</ x s l : i f >

</ x s l : f o r −e a c h >

</ x q b e>

</ x s l : t e m p l a t e>

</ x s l : s t y l e s h e e t >

Listing 5.1  Requête XQBE xad1 traduite en XSLT

<x q b e>

let $ doc := d o c ( " d a t a b a s e . xml " )


Chapitre 5 : Deuxième amélioration : l'axe ancêtre-descendant 34

Fig. 5.2  Requête XQBE xad2 executée sur dbase.

for $x in distinct −v a l u e s ( $ d o c / / t e x t ())

where

$ doc // t i t l e [ d e s c e n d a n t : : t e x t ( ) [ . = $ x ] ]

return

< t i t l e >{ $ x }</ t i t l e >

</ x q b e>

Listing 5.2  Requête XQBE xad1 traduite en XQuery

Dans cette très courte requête, au niveau du test, on utilise le chemin //


qui veut dire  descendant-or-self . C'est-à-dire qu'on descend sur n'importe
quel n÷ud du document, même la racine, et ce n÷ud doit avoir un ls title
qui lui-même possède un descendant texte avec la valeur de x. Le reste est
identique aux scripts précédents.

Exemple 7 : Cette seconde requête xad2 (g. 5.2) signie  donnez-moi le


titre des livres qui ont comme sujet XML  et sera executée sur dbase. Cette
requête est la même que la toute première que nous avons créée (g. 1.2),
la diérence est que nous n'avons plus les n÷uds catalog et slist. La requête
est donc plus simple à écrire.

<x s l : s t y l e s h e e t version =" 1 . 0 7 " x m l n s : x s l=" h t t p : / /www . w3 . o r g / 1 9 9 9 /XSL/ T r a n s f o r m ">

<x s l : t e m p l a t e match=" / ">

<x q b e>

<x s l : f o r −e a c h s e l e c t =" / / t e x t ( ) ">

<x s l : v a r i a b l e name=" x " s e l e c t =" . " />

<x s l : i f t e s t =" n o t ( p r e c e d i n g : : t e x t ( ) [ . = $ x ] ) ">

<x s l : i f t e s t =" / / b o o k [ d e s c e n d a n t : : t i t l e [ d e s c e n d a n t : : t e x t ( ) [ . = $ x ] ] ]
Chapitre 5 : Deuxième amélioration : l'axe ancêtre-descendant 35

[ d e s c e n d a n t : : s u b j e c t [ d e s c e n d a n t : : t e x t ( ) [ . = 'XML ' ] ] ] ">

< t i t l e >< x s l : v a l u e −o f s e l e c t = ' $ x ' /></ t i t l e >

</ x s l : i f >

</ x s l : i f >

</ x s l : f o r −e a c h >

</ x q b e>

</ x s l : t e m p l a t e>

</ x s l : s t y l e s h e e t >

Listing 5.3  Requête xad2 traduite en XSLT.

Dans cette requête, il y a un nouveau mot-clé qui est apparu et qui


est descendant. Comment comprendre le test ? Nous avons tout d'abord
//book qui veut dire :  du n÷ud-root, trouver un descendant book . De
là, trouver un descendant title qui a, lui même, un descendant texte avec la
valeur de la variable x, et un autre descendant subject qui a, lui également,
un descendant texte avec la valeur XML . Il n'y a que deux solutions possibles ;
les livres intitulés Databse et XML-RPC traitent bien un sujet XML.

5.1.1 Nouvelle règle

Reprenons l'ensemble de règles suivant : {RP1, RP2, RP3}, la règle


RS1 ne fait plus partie de notre ensemble. Cette règle qui utilisait l'axe
parent-enfant sera remplacée par la règle qui suit et qui utilise l'axe ancêtre-
descendant.
RS4 : si n est un n÷ud descendant de m dans d2, alors h(n) est un n÷ud
descendant de h(m) dans d1.

5.2 Fonctionnement avec l'ordre


Ce que nous voudrions faire ici, c'est de permettre à l'utilisateur d'uti-
liser la combinaison des deux améliorations précédentes. Nous allons vous
montrer un exemple de résultat souhaité et vous donner une explication du
fonctionnement.
La requête utilisée pour cet exemple est montrée à la gure 5.3. Nous
souhaitons récupérer tous les auteurs ainsi que le titre des livres qu'ils ont
écrits. Mais pour qu'un auteur soit repris, il faut que la balise <auteur>
précède celle du <titre>. Si on reprend le document dbase (g. 1.1), les
deux premiers livres suivent bien ce modèle. Par contre pour le troisième, le
titre précède les auteurs ; on ne prendra donc pas ce livre.
Avec cet exemple, on voit bien l'utilisation de l'axe ancêtre-descendant
car les n÷uds-élément author peuvent aussi bien être ls des n÷uds-élément
book que des n÷uds-élément alist. Quant à l'ordre, cela a déjà été expliqué
dans le paragraphe ci-dessus. Les réponses à cette requête sont présentées à
la gure 5.3.
Chapitre 5 : Deuxième amélioration : l'axe ancêtre-descendant 36

Fig. 5.3  Requête mélangeant l'ordre et l'axe ancêtre-descendant.

Nous n'avons pas réussi à implémenter cette combinaison des deux amé-
liorations, ni en XSLT, ni en XQuery. Dans ces deux langages, il manque
un axe. Pour utiliser l'ordre, nous devons utiliser soit following-sibling, soit
following. L'axe following-sibling ne peut pas être utilisé ici car les n÷uds ne
sont pas forcément frères. Par exemple, author n'est pas toujours un n÷ud
frère de title. following mais cet axe ne se li-
Nous pourrions alors utiliser
mite pas au sous-arbre de book. Prenons le sous-arbre de book dans lequel se
trouve le n÷ud author, si dans le programme, nous mettons quelque chose
comme author/following::title, comment préciser que title doit être pris
uniquement dans le sous-arbre de book dans lequel se trouve author ? Nous
n'avons pas trouvé la réponse à cette question.
Chapitre 6

Transformation d'une
requête XQBE

Jusqu'à présent, nous avons vu ce qu'était XQBE et comment l'utiliser.


Maintenant, nous allons étudier le code source des scripts de transformation,
ceux qui traduisent la requête XQBE en transformation XSLT ou en requête
XQuery.
Nous verrons tout d'abord le script de base. Pour les autres, nous n'a-
cherons que les lignes qui dièrent de ce premier script, et nous expliquerons
ces diérences.
Par souci de lisibilité, les scripts présents dans ce rapport ont été modi-
és, nous avons ajouté plusieurs retours à la ligne et modié certains carac-
tères. Ces modications ne sont pas présentes dans les scripts originaux et
ne doivent pas s'y trouver car le résultat pourrait être diérent.

6.1 Traduction vers XSLT


6.1.1 Script de base

1 version
−xml−
<x s l : s t y l e s h e e t =" 1 . 0 " x m l n s : x s l=" h t t p : / /www . w3 . o r g / 1 9 9 9 /XSL/ T r a n s f o r m ">

2 <x s l : o u t p u t omit d e c l a r a t i o n =" y e s " />

3 <x s l : t e m p l a t e match=" / ">

4 −o u t p u t − e s c a p i n g=" y e s ">
version
<x s l : t e x t disable

5 <x s l : s t y l e s h e e t =" 1 . 0 7 "

6 x m l n s : x s l=" h t t p : / /www . w3 . o r g / 1 9 9 9 /XSL/ T r a n s f o r m ">

7 <x s l : t e m p l a t e match=" / ">

8 </ x s l : t e x t >

9 <x q b e>

10 <! −− CREATION DES FOR−EACH POUR CHAQUE VARIABLE d e Q −−>


11 <x s l : f o r −e a c h s e l e c t =" / x q b e / body / / t e x t ( ) [ s t a r t s −w i t h ( . , ' # ' ) ] ">

12 <x s l : v a r i a b l e name=" h e l p " s e l e c t =" . " />

13 <x s l : i f t e s t =" n o t ( p r e c e d i n g : : t e x t ( ) [ . = $ h e l p ] ) ">

14 <x s l : t e x t disable −o u t p u t − e s c a p i n g=" y e s ">


15 <x s l : f o r −e a c h s e l e c t =" / / t e x t ( ) ">

16 <x s l : v a r i a b l e name="

17 </ x s l : t e x t >

18 <x s l : v a l u e −o f s e l e c t =" s u b s t r i n g ( . , 2 ) "/>


Chapitre 6 : Transformation d'une requête XQBE 38

19 <x s l : t e x t disable −o u t p u t − e s c a p i n g=" y e s ">


20 " s e l e c t =" . " />

21 <x s l : i f t e s t =" n o t ( p r e c e d i n g : : t e x t ( ) [ . = $

22 </ x s l : t e x t >

23 <x s l : v a l u e −o f s e l e c t =" s u b s t r i n g ( . , 2 ) "/>

24 <x s l : t e x t disable −o u t p u t − e s c a p i n g=" y e s ">


25 ] ) ">

26 </ x s l : t e x t >

27 </ x s l : i f >

28 </ x s l : f o r −e a c h>
29
30 <! −− CREATION DU TEST IF −−>
31 <x s l : t e x t disable −o u t p u t − e s c a p i n g=" y e s ">
32 <x s l : i f t e s t ="

33 </ x s l : t e x t >

34 <x s l : a p p l y − t e m p l a t e s s e l e c t =" / x q b e / body / ∗ "/>


35 <x s l : t e x t d i s a b l e −o u t p u t − e s c a p i n g=" y e s ">

36 ">

37 </ x s l : t e x t >

38
39 <! −− CREATION DU RESULTAT −−>
40 <x s l : a p p l y −t e m p l a t e s s e l e c t =" / x q b e / h e a d / ∗ " />
41
42 <! −− FERMETURE DE LA BALISE DU TEST IF −−>
43 <x s l : t e x t disable −o u t p u t − e s c a p i n g=" y e s ">
44 </ x s l : i f >

45 </ x s l : t e x t>

46
47 <! −− FERMETURE DES BALISES DES FOR−EACH −−>
48 <x s l : f o r −e a c h s e l e c t =" / x q b e / body / / t e x t ( ) [ s t a r t s −w i t h ( . , ' # ' ) ] ">

49 <x s l : v a r i a b l e name=" h e l p " s e l e c t =" . " />

50 <x s l : i f t e s t =" n o t ( p r e c e d i n g : : t e x t ( ) [ . = $ h e l p ] ) ">

51 <x s l : t e x t disable −o u t p u t − e s c a p i n g=" y e s ">


52 </ x s l : i f >

53 </ x s l : f o r −e a c h>
54 </ x s l : t e x t>

55 </ x s l : i f >

56 </ x s l : f o r −e a c h>
57 </ x q b e>

58
59 <x s l : t e x t disable −o u t p u t − e s c a p i n g=" y e s ">
60 </ x s l : t e m p l a t e>

61 </ x s l : s t y l e s h e e t >

62 </ x s l : t e x t >

63 </ x s l : t e m p l a t e>

64
65 <! −−TRAITEMENT DES NOEUDS AUTRES QUE LE NOEUD−ROOT DE Q. −−>
66 <x s l : t e m p l a t e match=" / x q b e / body / / ∗" p r i o r i t y =" 1 ">

67 [

68 <x s l : v a l u e − o f s e l e c t =" name ( ) " />


69 <x s l : a p p l y − t e m p l a t e s />
70 ]

71 </ x s l : t e m p l a t e>

72
73 <! −− TRAITEMENT DU NOEUD−ROOT DE Q. −−>
74 <x s l : t e m p l a t e match=" / x q b e / body / ∗" p r i o r i t y =" 2 ">

75 /

76 <x s l : v a l u e − o f s e l e c t =" name ( ) " />


77 <x s l : a p p l y − t e m p l a t e s />
78 </ x s l : t e m p l a t e>

79
80 <! −− TRAITEMENT DES NOEUDS−TEXTE NON VARIABLES AVEC UNE LONGUEUR > 0 DE Q −−>
Chapitre 6 : Transformation d'une requête XQBE 39

81 <x s l : t e m p l a t e match=" / x q b e / body / / t e x t ( ) [ s t r i n g − l e n g t h ( n o r m a l i z e −s p a c e ( . ) ) > 0 ] ">


82 <x s l : t e x t disable −o u t p u t − e s c a p i n g=" y e s ">
83 [.= '

84 </ x s l : t e x t >

85 <x s l : v a l u e −o f s e l e c t ="."/ >

86 <x s l : t e x t disable −o u t p u t − e s c a p i n g =" y e s ">


87 ' ]

88 </ x s l : t e x t >

89 </ x s l : t e m p l a t e>

90
91 <! −− TRAITEMENT DES NOEUDS−TEXTE NON VARIABLES AVEC UNE LONGUEUR = 0 DE Q −−>
92 <x s l : t e m p l a t e match=" / x q b e / body / / t e x t ( ) [ s t r i n g − l e n g t h ( n o r m a l i z e −s p a c e ( . ) ) = 0 ] " />

93
94 <! −− TRAITEMENT DES NOEUDS−TEXTE VARIABLES DE Q −−>
95 <x s l : t e m p l a t e match=" / x q b e / body / / t e x t ( ) [ s t a r t s −w i t h ( . , ' # ' ) ] ">

96 <x s l : t e x t disable −o u t p u t − e s c a p i n g=" y e s ">


97 [.=$

98 </ x s l : t e x t >

99 <x s l : v a l u e −o f s e l e c t =" s u b s t r i n g ( . , 2 ) " />

100 <x s l : t e x t disable −o u t p u t − e s c a p i n g=" y e s ">


101 ]

102 </ x s l : t e x t >

103 </ x s l : t e m p l a t e>

104
105 <! −− TRAITEMENT DES NOEUDS− ELEMENT DE R−−>
106 <x s l : t e m p l a t e match=" / x q b e / h e a d / / ∗ ">
107 < x s l : c o p y>

108 <x s l : a p p l y − t e m p l a t e s />


109 </ x s l : c o p y>

110 </ x s l : t e m p l a t e>

111
112 <! −− TRAITEMENT DES NOEUDS−TEXTE NON VARIABLES DE R −−>
113 <x s l : t e m p l a t e match=" / x q b e / h e a d / / t e x t ( ) " p r i o r i t y =" 1 ">

114 <x s l : v a l u e −o f s e l e c t =" . " />

115 </ x s l : t e m p l a t e>

116
117 <! −− TRAITEMENT DES NOEUDS−TEXTE VARIABLES DE R −−>
118 <x s l : t e m p l a t e match=" / x q b e / h e a d / / t e x t ( ) [ s t a r t s −w i t h ( . , '# ')] " p r i o r i t y =" 2 ">

119 <x s l : t e x t disable −o u t p u t − e s c a p i n g=" y e s ">


120 <x s l : v a l u e −o f s e l e c t= ' $

121 </ x s l : t e x t >

122 <x s l : v a l u e −o f s e l e c t =" s u b s t r i n g ( . , 2 ) " / >

123 <x s l : t e x t disable −o u t p u t − e s c a p i n g =" y e s ">


124 ' />

125 </ x s l : t e x t >

126 </ x s l : t e m p l a t e>

127 </ x s l : s t y l e s h e e t >

Listing 6.1  Code source du script de base

Le script est assez long, nous allons l'étudier partie par partie. Le script
du listing 3.1 que nous appelerons XT sera utilisé pour montrer le résultat
de la transformation. Dans les explications suivantes, pour chaque partie
expliquée, nous replacerons le code concerné pour ne pas devoir retourner à
chaque fois au code source de base.
La transformation ci-dessus contient plusieurs templates, on peut voir
cela comme des fonctions. Le premier commence à la ligne 3 et se termine à
la ligne 63. C'est le principale des templates et celui par où commencera la
Chapitre 6 : Transformation d'une requête XQBE 40

transformation.
Les balises <xsl :text> et </xsl :text> des lignes 4 et 8 s'assurent que
le processeur XSLT n'interprétera pas les lignes se trouvant entre ces deux
balises, il les recopiera dans le chier résultat. On peut donc placer du code
XSLT dans un script XSLT sans que ce code ne soit interprété. Les lignes 5 et
6 ne sont pas importantes pour le script en lui-même, elles sont utilisées par
le processeur XSLT ; cette ligne lui indique notamment la version de XSLT
utilisée dans le script et permet d'associer le namespace qui est ici xsl à une
adressse internet. La ligne 7 donne le résultat que l'on peut voir à la ligne 2
de XT. Nous avons ensuite la balise <xqbe> qui est recopiée dans le résultat.

4 −o u t p u t − e s c a p i n g=" y e s ">
version
<x s l : t e x t disable

5 <x s l : s t y l e s h e e t =" 1 . 0 7 "

6 x m l n s : x s l=" h t t p : / /www . w3 . o r g / 1 9 9 9 /XSL/ T r a n s f o r m ">

7 <x s l : t e m p l a t e match=" / ">

8 </ x s l : t e x t >

9 <x q b e>

Continuons avec le bloc qui va créer les for-each. Nous avons donc en
premier lieu, la ligne 11, un for-each qui va parcourir tous les n÷uds-texte
du corps de la requête présentant le caractère # en première position ; c'est-à-
dire uniquement les variables. À ligne 12, le contenu du n÷ud-texte est placé
dans la variable help. Cette variable contiendra donc une valeur comme  #x,
 #y  ou toute autre variable. Nous testons à la ligne 13 que le contenu de la
variable help n'a pas déjà été rencontré auparavant. Les lignes 14 à 26 vont
donner, dans XT, les lignes 4, 5 et 6. Les lignes 5 et 6 utilisent la variable
x car help avait comme contenu #x. Nous aurions eu un autre résultat si le
contenu de help avait été diérent.

11 <x s l : f o r −e a c h s e l e c t =" / x q b e / body / / t e x t ( ) [ s t a r t s −w i t h ( . , ' # ' ) ] ">

12 <x s l : v a r i a b l e name=" h e l p " s e l e c t =" . " />

13 <x s l : i f t e s t =" n o t ( p r e c e d i n g : : t e x t ( ) [ . = $ h e l p ] ) ">

14 <x s l : t e x t disable −o u t p u t − e s c a p i n g=" y e s ">


15 <x s l : f o r −e a c h s e l e c t =" / / t e x t ( ) ">

16 <x s l : v a r i a b l e name="

17 </ x s l : t e x t >

18 <x s l : v a l u e −o f s e l e c t =" s u b s t r i n g ( . , 2 ) "/>

19 <x s l : t e x t disable −o u t p u t − e s c a p i n g=" y e s ">


20 " s e l e c t =" . " />

21 <x s l : i f t e s t =" n o t ( p r e c e d i n g : : t e x t ( ) [ . = $

22 </ x s l : t e x t >

23 <x s l : v a l u e −o f s e l e c t =" s u b s t r i n g ( . , 2 ) "/>

24 <x s l : t e x t disable −o u t p u t − e s c a p i n g=" y e s ">


25 ] ) ">

26 </ x s l : t e x t >

27 </ x s l : i f >

28 </ x s l : f o r −e a c h>

Passons ensuite à la partie qui va créer le test if. Elle est composée des
lignes 31 à 37. Le résultat que l'on obtient est le test, dans XT, qui commence
Chapitre 6 : Transformation d'une requête XQBE 41

à la ligne 10 et qui se termine à la ligne 13. Cependant ce test n'est pas créé
entièrement dans ce bloc. Ici, nous n'allons créer que le début et la n de la
balise, c'est-à-dire <xsl:if test=" pour le début et "> pour la n. Pour le
reste, nous faisons appel à un autre template.

31 <x s l : t e x t disable −o u t p u t − e s c a p i n g=" y e s ">


32 <x s l : i f t e s t ="

33 </ x s l : t e x t >

34 <x s l : a p p l y − t e m p l a t e s s e l e c t =" / x q b e / body / ∗ "/>


35 <x s l : t e x t d i s a b l e −o u t p u t − e s c a p i n g=" y e s ">

36 ">

37 </ x s l : t e x t >

La ligne 40 appelle un template qui va créer les lignes 14 à 16 de XT ;


c'est-à-dire la partie qui correspond à la tête de la requête XQBE.
Nous arrivons enn à la dernière partie du premier template, la partie
dans laquelle on va fermer les balises. Les lignes 43 à 45 fonctionnent comme
les lignes 31 à 37, seule la sortie dière. Pour le bloc de lignes 48 à 56, le
fonctionnement est le même que le bloc de lignes 11 à 28.

43 <x s l : t e x t disable −o u t p u t − e s c a p i n g=" y e s ">


44 </ x s l : i f >

45 </ x s l : t e x t >

46
47 <x s l : f o r −e a c h s e l e c t =" / x q b e / body / / t e x t ( ) [ s t a r t s −w i t h ( . , ' # ' ) ] ">

48 <x s l : v a r i a b l e name=" h e l p " s e l e c t =" . " />

49 <x s l : i f t e s t =" n o t ( p r e c e d i n g : : t e x t ( ) [ . = $ h e l p ] ) ">

50 <x s l : t e x t disable −o u t p u t − e s c a p i n g=" y e s ">


51 </ x s l : i f >

52 </ x s l : f o r −e a c h>
53 </ x s l : t e x t >

54 </ x s l : i f >

55 </ x s l : f o r −e a c h>
56 </ x q b e>

57
58 <x s l : t e x t disable −o u t p u t − e s c a p i n g=" y e s ">
59 </ x s l : t e m p l a t e>

60 </ x s l : s t y l e s h e e t >

61 </ x s l : t e x t>

62 </ x s l : t e m p l a t e>

Le template que nous rencontrons à la ligne 66 et qui se termine à la


ligne 71 sera appellé pour chaque n÷ud-élément du corps de la requête qui
n'est ni le n÷ud-root, ni le n÷ud racine (ls de root ). Ils sont traités dans
l'ordre dans lequel ils apparaissent dans le chier. Chaque n÷ud que l'on
rencontre sera ajouté au test, il sera précédé et suivit d'un crochet comme
on peut le voir dans le test if de XT. Le script que nous utilisons est récursif,
lorsqu'il se trouve sur un n÷ud, il va faire appel à un template qui peut être
lui-même ; on voit l'appel récursif avec la ligne <xsl:apply-template/>. On
va donc de cette manière parcourir tous les n÷uds de la requête XQBE.
Chapitre 6 : Transformation d'une requête XQBE 42

66 <x s l : t e m p l a t e match=" / x q b e / body / / ∗" p r i o r i t y =" 1 ">

67 [

68 <x s l : v a l u e − o f s e l e c t =" name ( ) " />


69 <x s l : a p p l y − t e m p l a t e s />
70 ]

71 </ x s l : t e m p l a t e>

Le template qui commence à la ligne 74 et se termine à la ligne 78 fonc-


tionne de manière identique mais ne traite que le n÷ud racine du corps de
la requête car ce n÷ud doit être précédé du caractère /, il ne doit pas se
trouver entre crochets.

74 <x s l : t e m p l a t e match=" / x q b e / body / ∗" p r i o r i t y =" 2 ">

75 /

76 <x s l : v a l u e − o f s e l e c t =" name ( ) " />


77 <x s l : a p p l y − t e m p l a t e s />
78 </ x s l : t e m p l a t e>

Nous arrivons ensuite à trois templates qui traitent les n÷uds-texte du


corps de la requête.
Commençons par le premier. Il traite tous les n÷uds-texte qui ne sont
pas des variables et dont la longueur du texte est plus grande que 0. Pour
tous ces n÷uds, il inscrit dans l'ordre :
 la partie gauche qui est [.=' ;
 le contenu du n÷ud-texte courant ;
 la partie droite qui est '].
On a donc quelque chose comme [.='SQL Server'].

81 <x s l : t e m p l a t e match=" / x q b e / body / / t e x t ( ) [ s t r i n g − l e n g t h ( n o r m a l i z e −s p a c e ( . ) ) > 0 ] ">


82 <x s l : t e x t disable −o u t p u t − e s c a p i n g=" y e s ">
83 [.= '

84 </ x s l : t e x t >

85 <x s l : v a l u e −o f s e l e c t ="."/ >

86 <x s l : t e x t disable −o u t p u t − e s c a p i n g =" y e s ">


87 ' ]

88 </ x s l : t e x t >

89 </ x s l : t e m p l a t e>

Le deuxième template est un peu spécial. Cela peut paraître contradic-


toire de traiter des n÷uds-texte n'ayant pas de texte. Cependant, lorsque
l'on écrit une requête XQBE, on utilise un éditeur de texte classique et par
souci de clarté, on indente le code. C'est cette indentation qui peut poser
problème avec certains processeurs XSLT. Ils considèrent cette indentation
comme du texte et transforme donc mal la requête. Nous avons donc ajouté
un template qui ne fait rien pour tous ces n÷uds.
Chapitre 6 : Transformation d'une requête XQBE 43

92 <x s l : t e m p l a t e match=" / x q b e / body / / t e x t ( ) [ s t r i n g − l e n g t h ( n o r m a l i z e −s p a c e ( . ) ) = 0 ] " />

Le troisième template est celui qui va traiter les variables. Il ressemble au


premier de ces trois templates. Pour chaque variable, il inscrit dans l'ordre :
 la partie gauche qui est [.=$ ;
 le deuxième caractère du texte car le premier est le caractère # ;
 la partie droite qui est ].
On a par exemple : [.=$x].

95 <x s l : t e m p l a t e match=" / x q b e / body / / t e x t ( ) [ s t a r t s −w i t h ( . , ' # ' ) ] ">

96 <x s l : t e x t disable −o u t p u t − e s c a p i n g=" y e s ">


97 [.=$

98 </ x s l : t e x t >

99 <x s l : v a l u e −o f s e l e c t =" s u b s t r i n g ( . , 2 ) " />

100 <x s l : t e x t disable −o u t p u t − e s c a p i n g=" y e s ">


101 ]

102 </ x s l : t e x t >

103 </ x s l : t e m p l a t e>

Passons maintenant aux n÷uds de la tête de la requête. Le traitement


est plus facile. Tous les n÷uds qui ne sont pas des variables peuvent être
recopiés. Seuls les n÷uds variables doivent subir un traitement car il faut
remplacer la variable par sa valeur.
Trois templates vont traiter les n÷uds de la tête de la requête. Le premier
template que l'on rencontre à la ligne 106 va être appelé pour tous les n÷uds-
élément. Il ne fait que recopier les balises. Le deuxième template va gérer
tous les n÷uds-texte qui ne sont pas des variables. Ici aussi, on ne fait que
recopier le contenu du n÷ud. Et enn, le troisième des templates va, quant
à lui, remplacer la variable par sa valeur. Ce template va donc traiter tous
les n÷uds commençant par le caractère #. Le résultat de ces trois templates
peut être vu aux lignes 14 à 16 de XT.
106 <x s l : t e m p l a t e match=" / x q b e / h e a d / / ∗ ">
107 < x s l : c o p y>

108 <x s l : a p p l y − t e m p l a t e s />


109 </ x s l : c o p y>

110 </ x s l : t e m p l a t e>

111
112 <x s l : t e m p l a t e match=" / x q b e / h e a d / / t e x t ( ) " p r i o r i t y =" 1 ">

113 <x s l : v a l u e −o f s e l e c t =" . " />

114 </ x s l : t e m p l a t e>

115
116 <x s l : t e m p l a t e match=" / x q b e / h e a d / / t e x t ( ) [ s t a r t s −w i t h ( . , '# ')] " p r i o r i t y =" 2 ">

117 <x s l : t e x t disable −o u t p u t − e s c a p i n g=" y e s ">


118 <x s l : v a l u e −o f s e l e c t= ' $

119 </ x s l : t e x t >

120 <x s l : v a l u e −o f s e l e c t =" s u b s t r i n g ( . , 2 ) " / >

121 <x s l : t e x t disable −o u t p u t − e s c a p i n g =" y e s ">


122 ' />

123 </ x s l : t e x t>

124 </ x s l : t e m p l a t e>


Chapitre 6 : Transformation d'une requête XQBE 44

6.1.2 Script utilisant l'ordre

Ici, nous allons étudier la transformation XSLT avec les règles que nous
avons établies à la section 4.3. Nous n'avons placé qu'une partie du script,
le reste étant identique au script ci-dessus, il n'est pas utile de le placer ici.
La partie qui a été modiée concerne les lignes 66 à 71 du script précédent.
Ces lignes ont été remplacées par ce qui se trouve au listing 6.2. Un exemple
de résultat obtenu avec ce script peut être le script 4.3.

1 <x s l : t e m p l a t e match=" / x q b e / body / / ∗ ">


2 <x s l : i f t e s t =" . . / @ o r d e r [ . = ' y e s ' ] ">

3 <x s l : i f −s i b l i n g : : ∗)
t e s t =" c o u n t ( p r e c e d i n g != 0 ">

4 / following −s i b l i n g : :
5 < x s l : v a l u e −o f s e l e c t =" name ( ) " />

6 < x s l : a p p l y − t e m p l a t e s />

7 </ x s l : i f >

8
9 <x s l : i f t e s t =" c o u n t ( p r e c e d i n g −s i b l i n g : : ∗) = 0 ">

10 [

11 <x s l : v a l u e − o f s e l e c t =" name ( ) " />


12 <x s l : a p p l y − t e m p l a t e s />
13 </ x s l : i f >

14
15 <x s l : i f t e s t =" c o u n t ( f o l l o w i n g −s i b l i n g : : ∗) = 0 ">

16 ]

17 </ x s l : i f >

18 </ x s l : i f >

19
20 <x s l : i f t e s t =" n o t ( . . / @ o r d e r [ . = ' y e s ' ] ) ">

21 [

22 <x s l : v a l u e − o f s e l e c t =" name ( ) " />


23 <x s l : a p p l y − t e m p l a t e s />
24 ]

25 </ x s l : i f >

26 </ x s l : t e m p l a t e>

Listing 6.2  Code source du script XSLT utilisant l'ordre

Le template modié est celui qui parcourt les n÷uds-élément. Nous com-
mençons par tester, grâce aux lignes 2 et 20, si le n÷ud parent possède
l'attribut order avec la valeur  yes . Si ce n'est pas le cas, alors nous retom-
bons sur ce que nous avions déjà vu avec le script précédent, c'est-à-dire que
le n÷ud-élément est précédé et suivi de crochets.
Par contre si le n÷ud parent possède bien cet attribut, le traitement est
diérent. Le mot clé /following-sibling:: ne doit être placé qu'entre deux
frères. Nous testons, à la ligne 3, si le n÷ud courant possède un frère qui le
précède. Si tel est le cas alors on peut placer ce mot clé, pour ensuite placer
le nom du n÷ud et continuer le traitement sur les autres n÷uds. Par contre,
si le n÷ud est le premier des frères, il ne faut pas le faire précéder du mot-clé
/following-sibling::, nous aurions une erreur. Ce n÷ud doit être précédé
d'un crochet, c'est ce que font les lignes 9 à 13. Et enn, les lignes 15 à 18
testent si le n÷ud courant est le dernier des frères. Si c'est le cas, il faut alors
Chapitre 6 : Transformation d'une requête XQBE 45

fermer le crochet qui a été ouvert pour le premier des frères.


Le listing 4.3 nous montre bien le fonctionnement. Le n÷ud book n'ayant
pas d'attribut order, ses ls alist et title ne sont pas séparés par le mot clé
/following-sibling::. Par contre, le n÷ud alist possède bien cet attribut,
ce qui a pour conséquence que les deux n÷uds author sont séparés par ce
mot-clé. Le premier author est bien précédé d'un crochet et le dernier est
bien suivi d'un crochet.

6.1.3 Le script pour l'axe ancêtre-descendant

1 <x s l : t e m p l a t e match=" / x q b e / body / / ∗" p r i o r i t y =" 1 ">

2 [ descendant::

3 <x s l : v a l u e − o f s e l e c t =" name ( ) " />


4 <x s l : a p p l y − t e m p l a t e s />
5 ]

6 </ x s l : t e m p l a t e>

7
8 <x s l : t e m p l a t e match=" / x q b e / body / ∗" p r i o r i t y =" 2 ">

9 //

10 <x s l : v a l u e − o f s e l e c t =" name ( ) " />


11 <x s l : a p p l y − t e m p l a t e s />
12 </ x s l : t e m p l a t e>

13
14 <x s l : t e m p l a t e match=" / x q b e / body / / t e x t ( ) [ s t r i n g − l e n g t h ( n o r m a l i z e −s p a c e ( . ) ) > 0 ] ">
15 <x s l : t e x t disable −o u t p u t − e s c a p i n g=" y e s ">
16 [ descendant::text ()[.= '

17 </ x s l : t e x t >

18 <x s l : v a l u e −o f s e l e c t ="."/ >

19 <x s l : t e x t disable −o u t p u t − e s c a p i n g =" y e s ">


20 ' ]]

21 </ x s l : t e x t>

22 </ x s l : t e m p l a t e>

23
24 <x s l : t e m p l a t e match=" / x q b e / body / / t e x t ( ) [ s t r i n g − l e n g t h ( n o r m a l i z e −s p a c e ( . ) ) = 0 ] " />
25
26 <x s l : t e m p l a t e match=" / x q b e / body / / t e x t ( ) [ s t a r t s −w i t h ( . , ' # ' ) ] ">

27 <x s l : t e x t disable −o u t p u t − e s c a p i n g=" y e s ">


28 [ descendant::text ()[.=$

29 </ x s l : t e x t>

30 <x s l : v a l u e −o f s e l e c t =" s u b s t r i n g ( . , 2 ) " />

31 <x s l : t e x t disable −o u t p u t − e s c a p i n g=" y e s ">


32 ]]

33 </ x s l : t e x t>

34 </ x s l : t e m p l a t e>

Listing 6.3  Code source du script pour l'axe ancêtre-descendant

Ce script comporte plus de changement que le précédent. Le fait est qu'ici,


chaque n÷ud subira une modication, pas seulement les n÷uds frères dont
le parent possède l'attribut order. Les changements concernent les lignes 66
à 103 du premier script, elles sont remplacées par les lignes présentes dans
le listing 6.3.
Dans le premier template, le crochet est maintenant remplacé par [descendant::
pour préciser que le n÷ud est un descendant. En fait, le crochet que nous
Chapitre 6 : Transformation d'une requête XQBE 46

avions placé est une abbréviation pour [child::.


Pour le second template, au lieu d'utiliser le chemin /, nous utilisons le
chemin // car le n÷ud se trouvant à la racine du corps de la requête ne doit
plus nécessairement être mappé sur le n÷ud racine du document XML.
Le troisième et le cinquième template sont presque identiques, le troisième
travaille sur les n÷uds textes  normaux , tandis que le cinquième travaille
sur les n÷uds-texte qui contiennent une variable. Ici aussi, nous devions
spécier que le n÷ud-texte ne doit plus être uniquement un ls mais bien un
descendant. On le voit grâce aux lignes 16 et 28.

6.2 Traduction vers XQuery


Voyons maintenant les scripts qui traduisent les requêtes XQBE en re-
quête XQuery. Nous n'allons pas réexpliquer chaque script en détail. Seul le
résultat du script est diérent mais le fonctionnement et le traitement des
requêtes XQBE reste identique.

6.2.1 Script de base

1 version
−xml−
<x s l : s t y l e s h e e t =" 1 . 0 " x m l n s : x s l=" h t t p : / /www . w3 . o r g / 1 9 9 9 /XSL/ T r a n s f o r m ">

2 <x s l : o u t p u t omit d e c l a r a t i o n =" y e s " />

3 <x s l : t e m p l a t e match=" / ">

4 <x q b e>

5 <x s l : t e x t disable −o u t p u t − e s c a p i n g=" y e s ">


6 {

7 let $ doc := doc ( " " )

8 </ x s l : t e x t >

9
10 <x s l : f o r −e a c h s e l e c t =" / x q b e / body / / t e x t ( ) [ s t a r t s −w i t h ( . , ' # ' ) ] ">

11 <x s l : v a r i a b l e name=" h e l p " s e l e c t =" . " />

12 <x s l : i f t e s t =" n o t ( p r e c e d i n g : : t e x t ( ) [ . = $ h e l p ] ) ">

13 <x s l : t e x t disable −o u t p u t − e s c a p i n g=" y e s ">


14 for $

15 </ x s l : t e x t>

16 <x s l : v a l u e −o f s e l e c t =" s u b s t r i n g ( . , 2 ) " />

17 <x s l : t e x t disable −o u t p u t − e s c a p i n g=" y e s ">


18 in distinct −v a l u e s ( $ d o c / / t e x t ( ) )
19 </ x s l : t e x t>

20 </ x s l : i f >

21 </ x s l : f o r −e a c h>
22
23 <x s l : t e x t disable −o u t p u t − e s c a p i n g=" y e s ">
24 where

25 $ doc

26 </ x s l : t e x t>

27 <x s l : a p p l y −t e m p l a t e s s e l e c t =" / x q b e / body / ∗ " />


28
29 <x s l : t e x t disable −o u t p u t − e s c a p i n g=" y e s ">
30 return

31 </ x s l : t e x t>

32 <x s l : a p p l y −t e m p l a t e s s e l e c t =" / x q b e / h e a d / ∗ " />


33
34 <x s l : t e x t disable −o u t p u t − e s c a p i n g=" y e s ">
Chapitre 6 : Transformation d'une requête XQBE 47

35 }

36 </ x s l : t e x t >

37 </ x q b e>

38 </ x s l : t e m p l a t e>

39
40 <x s l : t e m p l a t e match=" / x q b e / body / / ∗ ">
41 [

42 <x s l : v a l u e − o f s e l e c t =" name ( ) " />


43 <x s l : a p p l y − t e m p l a t e s />
44 ]

45 </ x s l : t e m p l a t e>

46
47 <x s l : t e m p l a t e match=" / x q b e / body / ∗ ">
48 /

49 <x s l : v a l u e − o f s e l e c t =" name ( ) " />


50 <x s l : a p p l y − t e m p l a t e s />
51 </ x s l : t e m p l a t e>

52
53 <x s l : t e m p l a t e match=" / x q b e / body / / t e x t ( ) [ s t r i n g − l e n g t h ( n o r m a l i z e −s p a c e ( . ) ) > 0 ] ">
54 <x s l : t e x t disable −o u t p u t − e s c a p i n g=" y e s ">
55 [.= '

56 </ x s l : t e x t >

57 <x s l : v a l u e −o f s e l e c t ="."/ >

58 <x s l : t e x t disable −o u t p u t − e s c a p i n g =" y e s ">


59 ' ]

60 </ x s l : t e x t >

61 </ x s l : t e m p l a t e>

62
63 <x s l : t e m p l a t e match=" / x q b e / body / / t e x t ( ) [ s t r i n g − l e n g t h ( n o r m a l i z e −s p a c e ( . ) ) = 0 ] " />

64
65 <x s l : t e m p l a t e match=" / x q b e / body / / t e x t ( ) [ s t a r t s −w i t h ( . , ' # ' ) ] ">

66 <x s l : t e x t disable −o u t p u t − e s c a p i n g=" y e s ">


67 [.=$

68 </ x s l : t e x t >

69 <x s l : v a l u e −o f s e l e c t =" s u b s t r i n g ( . , 2 ) " />

70 <x s l : t e x t disable −o u t p u t − e s c a p i n g=" y e s ">


71 ]

72 </ x s l : t e x t >

73 </ x s l : t e m p l a t e>

74
75 <x s l : t e m p l a t e match=" / x q b e / h e a d / / ∗ ">
76 < x s l : c o p y>

77 <x s l : a p p l y − t e m p l a t e s />
78 </ x s l : c o p y>

79 </ x s l : t e m p l a t e>

80
81 <x s l : t e m p l a t e match=" / x q b e / h e a d / / t e x t ( ) ">

82 <x s l : v a l u e −o f s e l e c t =" . " />

83 </ x s l : t e m p l a t e>

84
85 <x s l : t e m p l a t e match=" / x q b e / h e a d / / t e x t ( ) [ s t a r t s −w i t h ( . , ' # ' ) ] ">

86 <x s l : t e x t disable −o u t p u t − e s c a p i n g=" y e s ">


87 {$

88 </ x s l : t e x t >

89 <x s l : v a l u e −o f s e l e c t =" s u b s t r i n g ( . , 2 ) " />

90 <x s l : t e x t disable −o u t p u t − e s c a p i n g=" y e s ">


91 }

92 </ x s l : t e x t >

93 </ x s l : t e m p l a t e>

94 </ x s l : s t y l e s h e e t >

Listing 6.4  Script de base pour la transformation vers XQuery


Chapitre 6 : Transformation d'une requête XQBE 48

6.2.2 Script utilisant l'ordre

1 <x s l : t e m p l a t e match=" / x q b e / body / / ∗" p r i o r i t y =" 1 ">

2 <x s l : i f t e s t =" . . / @ o r d e r [ . = ' y e s ' ] ">

3 <x s l : i f −s i b l i n g : : ∗)
t e s t =" c o u n t ( p r e c e d i n g != 0 ">

4 / following −s i b l i n g : :
5 < x s l : v a l u e −o f s e l e c t =" name ( ) " />

6 < x s l : a p p l y − t e m p l a t e s />

7 </ x s l : i f >

8
9 <x s l : i f t e s t =" c o u n t ( p r e c e d i n g −s i b l i n g : : ∗) = 0 ">

10 [

11 <x s l : v a l u e − o f s e l e c t =" name ( ) " />


12 <x s l : a p p l y − t e m p l a t e s />
13 </ x s l : i f >

14
15 <x s l : i f t e s t =" c o u n t ( f o l l o w i n g −s i b l i n g : : ∗) = 0 ">

16 ]

17 </ x s l : i f >

18 </ x s l : i f >

19
20 <x s l : i f t e s t =" n o t ( . . / @ o r d e r [ . = ' y e s ' ] ) ">

21 [

22 <x s l : v a l u e − o f s e l e c t =" name ( ) " />


23 <x s l : a p p l y − t e m p l a t e s />
24 ]

25 </ x s l : i f >

26 </ x s l : t e m p l a t e>

Listing 6.5  Script pour la transformation vers XQuery utilisant l'ordre

Cette partie remplace les lignes 40 à 45 du script de base. Nous plaçons le


mot-clé following-sibling entre deux frères si leur n÷ud parent a l'attribut
order à yes. Il faut cependant faire attention car ce mot-clé n'est pas
supporté par tous les processeurs XQuery. La spécication précise que les
développeurs des diérents processeurs XQuery sont libres d'implémenter cet
axe mais que ce n'est pas obligatoire. Cependant, la plupart des processeurs
tendent à supporter cet axe (ainsi que d'autres axes que nous n'utilisons pas
ici), nous nous sommes donc permis de l'utiliser.

6.2.3 Le script pour l'axe ancêtre-descendant

1 <x s l : t e m p l a t e match=" / x q b e / body / / ∗" p r i o r i t y =" 1 ">

2 [ descendant::

3 <x s l : v a l u e − o f s e l e c t =" name ( ) " />


4 <x s l : a p p l y − t e m p l a t e s /> ]</ x s l : t e m p l a t e>
5
6 <x s l : t e m p l a t e match=" / x q b e / body / ∗" p r i o r i t y =" 2 ">

7 //

8 <x s l : v a l u e − o f s e l e c t =" name ( ) " />


9 <x s l : a p p l y − t e m p l a t e s />
10 </ x s l : t e m p l a t e>

11
12 <x s l : t e m p l a t e match=" / x q b e / body / / t e x t ( ) [ s t r i n g − l e n g t h ( n o r m a l i z e −s p a c e ( . ) ) > 0 ] " p r i o r i t y =" 1 ">

13 <x s l : t e x t disable −o u t p u t − e s c a p i n g=" y e s ">


Chapitre 6 : Transformation d'une requête XQBE 49

14 [ d e s c e n d a n t : : t e x t ()[.=& apos ;

15 </ x s l : t e x t >

16 <x s l : v a l u e −o f s e l e c t =" . " />

17 <x s l : t e x t disable −o u t p u t − e s c a p i n g=" y e s ">


18 &a p o s ; ] ]

19 </ x s l : t e x t >

20 </ x s l : t e m p l a t e>

21
22 <x s l : t e m p l a t e match=" / x q b e / body / / t e x t ( ) [ s t r i n g − l e n g t h ( n o r m a l i z e −s p a c e ( . ) ) = 0 ] " />
23
24 <x s l : t e m p l a t e match=" / x q b e / body / / t e x t ( ) [ s t a r t s −w i t h ( . , '# ')] " p r i o r i t y =" 2 ">

25 <x s l : t e x t disable −o u t p u t − e s c a p i n g=" y e s ">


26 [ descendant::text ()[.=$

27 </ x s l : t e x t >

28 <x s l : v a l u e −o f s e l e c t =" s u b s t r i n g ( . , 2 ) " />

29 <x s l : t e x t disable −o u t p u t − e s c a p i n g=" y e s ">


30 ]]

31 </ x s l : t e x t >

32 </ x s l : t e m p l a t e>

Listing 6.6  Script pour la transformation vers XQuery utilisant l'axe


ancêtre-descendant
Chapitre 7

Complexité du problème

Nous montrerons tout d'abord que trouver un homomorphisme entre


deux documents XML est un problème NP-complet. Nous calculerons en-
suite la complexité de l'algorithme utilisé pour trouver toutes les réponses à
une requête XQBE.

7.1 Problème NP-dicile


Dans cette section, nous allons montrer que trouver un homomorphisme
entre deux documents XML est dicile, c'est à dire qu'il n'existe pas d'al-
gorithme qui fonctionne en temps polynomiale.
Pour cela, nous allons nous baser sur un problème similaire mais sur les
graphes. Lorsque nous avons deux graphes, tester s'il existe un homomor-
phisme entre ces deux graphes est un problème NP-complet. Nous dénirons
deux choses, tout d'abord ce qu'est un graphe et ensuite, ce qu'est un ho-
momorphisme entre deux graphes.

Dénition 4 : Soit G = (V, E), un graphe non-orienté avec V un ensemble


de sommets et E un ensemble d'arcs. Chaque arc est noté de la forme {v1 , v2 },
v1 , v2 ∈ V et v1 6= v2 . Nous n'avons donc pas de boucle.

Dénition 5 : Soit G1 = (V1 , E1 ) et G2 = (V2 , E2 ). Alors G1 ∗ G2 ssi il


existe f : V2 → V1 tel que si {v1 , v2 } ∈ E2 , alors {f (v1 ), f (v2 )} ∈ E1 . Ce
problème correspond à rechercher un homomorphisme entre deux graphes.
Il a déjà été prouvé que ce problème est NP-complet.

Exemple 8 : Ce premier exemple utilise les graphes montrés aux gures


7.1 et 7.2. Sur ces gures, nous avons en plus, l'encodage des graphes dans
un document XML. Ce que nous voulons montrer avec cet exemple est que
s'il existe un θ tel que gA ∗ θ(gB) alors dA  θ(dB). La contraposée est
également vraie.
Prenons θ = {(#x, B), (#y, V ), (#z, B), (#w, V )}. Si on utilise cette
dénition de θ alors θ(gB) est homomorphique à gA. On le voit facilement
Chapitre 7 : Complexité du problème 51

Fig. 7.1  Le graphe gA et le document XML dA.

Fig. 7.2  Le graphe gB et le document XML dB.


Chapitre 7 : Complexité du problème 52

Fig. 7.3  Le graphe gC et le document XML dC.

car tous les arcs existent bien dans gA ; on peut donc tous les mapper. Pour
ce qui est du document XML, en appliquant la même évaluation, on obtient
le document θ(dB) qui est homomorphique à dA.

Exemple 9 : Prenons le graphe gC et le document dC montrés à la gure


7.3. Le graphe ainsi que le document ressemblent fortement à ceux utili-
sés dans l'exemple 8, nous y avons juste ajouté deux arcs. Ainsi, tous les
sommets sont reliés entre-eux. Avec cet exemple, nous ne trouverons pas
d'homomorphisme, aussi bien pour le graphe que pour le document XML.
Partons du graphe, celui-ci contient quatre variables. En prenant θ(#x) = R,
θ(#y) = V et θ(#z) = B , nous pouvons relier trois sommets entre-eux de
sorte que les arcs qui les relient puissent être mappés sur gA. Cependant
il existe un quatrième sommet qui est relié avec les trois autres. Les seules
valeurs que ce sommet peut prendre sont {R, V, B} car ce sont les seules
valeurs qui existent dans gA. Quelque-soit la valeur que prendra le sommet,
on créera un arc qui a ses deux sommets avec la même valeur (ex : {R, R})
or un tel arc n'existe pas dans gA, il nous est donc impossible de trouver un
homomorphisme entre ces deux graphes.
Si maintenant, on applique la même évaluation θ sur le document XML, il
est facile de vérier que θ(dC) n'est pas homomorphique à dA. Intuitivement
on le voit car, après l'évaluation, il existera un arc qui a ses deux ls s1 et
s2 avec pour n÷ud-texte, le même contenu or un tel arc n'existe pas dans
dC.
Chapitre 7 : Complexité du problème 53

Intuitivement, on pourrait se dire qu'il existe un homomorphisme entre


deux graphes si et seulement si il existe un homomorphisme entre les docu-
ments XML représentant ces graphes. Nous allons le démontrer.

7.1.1 Démonstration

Reprenons gA = (Va , Ea ) avec Va = {R, V, B} et


Ea = {{R, V } , {V, B} , {B, R}} comme graphe de base et dA comme docu-
ment qui encode ce graphe. Pour tous les arcs de dA, les n÷uds s1 et s2 ont
un contenu qui n'est pas identique, de plus, ce contenu est pris également
dans l'ensemble Va .
Nous prendrons gD = (Vd , Ed ), un graphe dont les sommets peuvent être
des variables et dD, le document XML qui encode ce graphe.

Première partie de la preuve : Nous allons montrer que s'il existe une
évaluation θ de sorte que θ(gD) soit homomorphique à gA alors θ(dD) est
homomorphique à dA. Nous prendrons T = {R, V, B}, l'ensemble de tous les
n÷uds-texte de dA.
Nous allons procéder par l'absurde et partirons de l'hypothèse qu'il n'est
pas possible de trouver un homomorphisme dA  θ(dD) (1).
Par (1), on peut dire que l'évaluation θ(dD) donnera toujours
un arc Z
qui soit inexistant dansdA. Les seuls cas possibles sont que :
1. Z ait, au moins, un de ses deux ls, s1 ou s2, dont le contenu ∈
/T;
2. les deux ls de Z, s1 et s2, ont le même contenu texte.

Commençons par traiter le premier cas. Étant donné que θ(dD) est un
encodage du graphe θ(gD), cela veut dire que θ(gD) possède au moins un
sommet avec une valeur qui ne soit pas dans Va . De ce fait, il est claire-
ment impossible de trouver un homomorphisme entre ces deux graphes ; on
contredit donc l'hypothèse  θ(gD) est homomorphique à gA .
Passons maintenant au deuxième cas. Pour que s1 et s2 aient le même
contenu texte, il faut que dans θ(gD), il y ait un arc e = {v3 , v3 }, or un tel
arc n'existe pas dans gA. Ce qui implique qu'on ne peut pas trouver d'ho-
momorphisme entre ces deux graphes. Mais cela contredit notre hypothèse
du départ qui disait que θ(gD) est homomorphique à gA.

Deuxième partie de la preuve : Nous montrerons l'autre implication.


S'il existe une évaluation θ de sorte que θ(dD) soit homomorphique à dA
alors gA ∗ θ(gD).
Ici également, nous procéderons par l'absurde. Prenons l'hypothèse que
θ(gD) ne soit pas homomorphique à gA. Cela signie que dans θ(gD), il
existe un arc e = (d1 , d2 ) qui ne puisse pas être mappé vers un arc de gA.
Ici aussi on a deux cas possibles :

1. soit d1 soit d2 ∈
/ Va ;
Chapitre 7 : Complexité du problème 54

2. soit d1 = d2 ; cela peut soit dire que l'on a une boucle, soit que l'arc e
relie deux sommets de même valeur.

Si d1 ou d2 ∈
/ Va , cela implique que dans θ(dD), il y ait un arc dont
l'un des sommets ( s1 ou s2 ) a un contenu qui ne se trouve pas dans Va .
Et donc θ(dD) n'est pas homomorphique à dA. On a une contradiction avec
l'hypothèse de départ.
Si on est dans le cas d1 = d2 , on aura alors dans θ(dD) un arc Z dont
les deux sommets s1 et s2 ont un contenu identique. Un tel arc n'existe pas
dans dA, ce qui implique que Z ne peut pas être mappé vers un arc de dA. Et
donc θ(dD) n'est pas homomorphique à dA. Ce qui encore une fois contredit
l'hypothèse de départ.

Grâce à cette double implication, nous pouvons dire que trouver un ho-
momorphisme entre deux documents XML est un problème NP-dicile.

7.2 Problème NP
Prenons deux documents XML np1 et np2 quelconques. Nous venons de
montrer que trouver un homomorphisme np1  np2 est un problème NP-
dicile. Par contre, si on nous donne l'homomorphisme, il est très facile de
vérier s'il est correcte. Par facile, il faut entendre qu'il existe un algorithme
en temps polynomiale.
Pour vérier les règles RP1, RP2 et RP3 (voir section 1), on peut utiliser
un algorithme avec une complexité linéaire. Il sut de parcourir les n n÷uds
du document np2 et pour chacun d'eux tester les trois règles. Chacune des
règles peut être testée en temps constant.
Pour vérier les règles secondaires, c'est-à-dire RS1 (Ÿ1), RS2 (Ÿ4.2.2),
RS3 (Ÿ4.3.2) et RS4 (Ÿ5.1.1) on peut utilise un algorithme naïf qui a une
complexité en O(n2 ). Nous procédons de la manière suivante : nous prenons
deux n÷uds diérents dans np2 et nous testons les règles pré-citées en fonc-
tion du  type  d'homomorphisme souhaité. Chacune des règles peut être
testée en temps constant. Dans le pire des cas, nous allons tester chacun des
n÷uds avec tous les autres et donc on procède à n2 tests.
On a donc bien un algorithme donc la complexité est en O(n2 ), le pro-
blème est donc bien en NP.

7.3 Complexité
Prenons n, le nombre de n÷ud-texte dans le document XML dA et m, le
nombre de variable dans la requête dB. Dans le pire des cas, tous les n÷uds-
texte de dA sont diérents. Si nous reprenons le script 3.1, nous avions utilisé
deux variables. Dans le script, nous avons donc deux boucles imbriquées, la
Chapitre 7 : Complexité du problème 55

complexité est de n2 . On peut donc dire que pour m variables, nous avons
nm . La complexité est donc de O(nm ).
Chapitre 8

Conclusion

Nous en arrivons à la n de ce travail. Dans l'introduction, nous avions


annoncé que nous allions créer un nouveau langage de requêtes. Ce que nous
avons fait en dénissant, tout d'abord, le langage ainsi que les diérentes
règles. Nous avons ensuite proposé une manière d'écrire les requêtes XQBE
dans un document XML. Beaucoup de monde peut trouver un grand in-
térêt dans ce langage. Grâce à XQBE, on peut dorénavant questionner un
document XML sans avoir des connaisances en XQuery, XSLT, XPath, etc.
XQBE suit donc exactement la même idée que QBE mais est entièrement
adapté aux documents XML. Avoir choisi XML comme langage de requête
est certainement un choix très judicieux du fait que nous travaillons sur des
documents XML.
Nous avons ensuite implémenté un algorithme en XSLT qui permet de
transformer une requête XQBE en XSLT ou en XQuery. Cet algorithme
fonctionne très bien et retourne toujours le résultat attendu. Ce script est
à mon avis, quelque chose de très complémentaire au langage lui-même. Il
n'y a aucun intérêt à écrire des requêtes XQBE s'il faut par après écrire les
requêtes en XSLT ou XQuery à la main.
Nous sommes ensuite passés aux extensions. Nous avons commencé par
l'ordre (chapitre 4). Le support de l'ordre dans le langage XQBE est quelque
chose d'important car l'ordre est intrinsèque à XML. En utilisant l'ordre,
avec la même requête, le fait d'utiliser le n÷ud-attribut order ou non, nous
donnera un résultat diérent. La deuxième amélioration que nous avons ap-
pelée  axe ancêtre-descendant  (voir chapitre 5) permet aux utilisateurs de
créer des requêtes alors qu'ils ne connaissent pas forcément toute la structure
du document XML.
Concernant la vitesse d'exécution des scripts XQuery et XSLT qui cherchent
les réponses, on remarquera facilement qu'ils sont assez lents lorsque la taille
de la requête devient conséquente. On peut bien sûr améliorer l'algorithme
pour rendre l'exécution plus rapide mais il est  impossible  de trouver
un algorithme qui fonctionne en temps polynomiale car le problème est NP-
complet (si on a bien P 6= N P ), ce que nous avons démontré à la section
7.1. C'est peut-être un point négatif mais, il ne faut pas confondre XQBE
Chapitre 8 : Conclusion 57

avec les autres langages tel que XQuery. Nous n'avons pas créé un langage
 Turing-complet , il est donc impossible de faire en XQBE, les même re-
quêtes qu'en XQuery. On essayera donc de créer des requêtes simples qui
ne contiennent que quelques variables. Et dans ce cas, le temps d'exécution
restera  raisonable .

8.1 Travaux futurs


Dans notre mémoire, plusieurs points ont été laissés en suspend, nous
allons les énumérer ici, ainsi que décrire succinctement en quoi cela consiste.

À la section 3.3, nous avions parlé des doublons. Ce problème peut de-
venir très complexe. En eet, les doublons peuvent être perçus diéremment
par diérentes personnes. On pourrait dire que nous avons des doublons si
deux réponses sont idéntiques. Mais nous tombons alors sur un autre pro-
blème, qu'entendons-nous par  réponses identiques  ? Le but du mémoire
n'étant pas de trouver une solution à ce problème, nous avons préféré nous
en tenir à la solution qui nous semblait susamment adaptée pour la suite
du mémoire mais nous ne prétendons pas que c'est la meilleure solution.
On pourrait améliorer la spécication pour supporter tous les n÷uds.
Il manque le support des n÷uds-attribut, -commentaire, -namespace et -
processing instruction. Les n÷uds-attributs peuvent très certainement ap-
porter beaucoup d'informations car se sont des n÷uds qui sont énormément
utilisés dans les documents XML. L'avantage est qu'il n'ont ni le problème
de l'ordre ni le problème de l'axe ancêtre-descendant ; ils peuvent donc être
supportés assez facilement mais en faisant attention que l'attribut order
dans une requête XQBE a un sens particulier.
À la section 5.2, nous parlions de mélanger l'ordre avec l'axe ancêtre-
descendant. Par manque de temps, nous n'avons pas pu trouver une implé-
mentation qui permet ce mélange. On peut donc chercher comment implé-
menter cela et, par la suite, trouver quels sont les nouveaux problèmes qui
peuvent survenir.
Dans nos requêtes, toutes les variables sont situées uniquement dans les
n÷uds-texte. Il serait intéressant d'étudier le fonctionnement en permettant
l'utilisation de variables sur tous les n÷uds ou, du moins, dans les n÷uds-
élément et -attribut.

8.2 Travail relatif


Des recherches sont réalisées par Daniele Braga, Alessandro Campi et Ste-
fano Cerri dans le but d'obtenir un XQBE[1]. Leur travail est certainement
plus évolué que le nôtre, cependant nous verrons que sur certains points, il
y a de grandes ressemblances. Nous décrirons donc, en quelques lignes, quels
Chapitre 8 : Conclusion 58

sont les points communs et les diérences entre nos deux XQBE. Pour dif-
férencier nos deux XQBE, nous appelerons notre langage par XQBEN et le
leur par XQBEL .
Commençons tout d'abord par comparer le langage en lui-même. Tout
d'abord, les requêtes sont écrites de manière visuelle. Ils ont donc mis en place
diérents types de n÷uds et d'axes qui permettent de former les requêtes.
Si l'on prend l'ensemble de tous les n÷uds existant en XQBEL , ils ont
déni un sous-ensemble de n÷uds qui forment le CoreXQBE. Cet ensemble
forme donc la base du langage alors que le reste est à considerer comme
une extension. Cependant, leurs requêtes sont également composées de deux
parties. Ils ont une partie gauche qui représente notre body et une partie
droite qui représente notre head.
Dans notre langage, nous nous sommes limités aux n÷uds-texte et n÷uds-
élement. Par contre, en XQBEL , les n÷uds-attributs sont supportés. Dans
ces n÷uds, les  variables  sont également acceptées. Mais comme nous
l'avons déjà précisé dans la section précédente, pour XQBEN , ceci peut
faire partie des recherches futures.
Un point intéressant dans leur langage que nous n'avons pas essayé
d'implémenter, c'est l'utilisation d'opérateurs de comparaison. Par exemple,
lorsque nous plaçons un texte dans un n÷ud-élément (<title>SQL</title>),
nous demandons à trouver des réponses dont le titre vaut exactement ce texte
(SQL ). Mais il se peut que dans certains cas, nous voulions le contraire, par
exemple les n÷uds dont le titre n'est pas SQL . Dans ce cas, les opérateurs
de comparaison permettent d'écrire des requêtes que nous n'aurions pas pu
écrire autrement.
En dehors de ces quelques diérences mineures, leur langage apporte
quelque chose de très intéressant. Si nous reprenons notre langage, dans la
partie head, nous devons explicitement dénir comment doit être aché le
résultat. Si nous voulons acher toutes les informations d'un livre, nous
devons inclure une variable pour chacune des informations qui nous inté-
resse. Par exemple pour le code ISBN, il faudra, inclure une variable (ex :
<isbn>#x</isbn>) dans la partie body qui sera réutilisée dans la partie head.
Pour que cela fonctionne bien, il faudrait que tous les livres contiennent une
balise <isbn>. Et donc tous les livres n'ayant pas de code ISBN ne seront
pas repris dans le résultat. Pour éviter ce genre de problème, en XQBEL ,
ils fonctionnent de cette manière :
 dans la partie gauche de leur requête, ils mettent juste le nécessaire
pour parcourir tous les livres (ex : <catalog><book/></catalog>) ;
 dans la partie droite, ils placent un n÷ud-élément pour lequel ils pré-
cisent que tout le sous-arbre doit être repris, quel qu'il soit ;
 enn, ils vont lier la partie gauche à la partie droite.
de cette manière, grâce à la partie gauche, on va parcourir tous les livres et,
pour chacun d'eux, on va récupérer tout le sous-arbre qui sera alors aché
dans la réponse.
Chapitre 8 : Conclusion 59

Passons maintenant à la recherche de réponses. On retrouve cette idée


d'homorphisme, c'est-à-dire qu'il dénissent des règles à respecter pour qu'une
réponse soit valide. Ici aussi, ils vont passer par une étape intermédiaire qui
correspond à la traduction d'une requête XQBE. On remarque donc que nos
deux XQBE sont fort proches sur ce point. Par contre, ils n'utilisent pas
XSLT pour transformer leurs requêtes XQBE, ce qui est tout-à-fait logique
étant donné qu'elles ne sont pas écrites en XML. Ils ont donc développé un
moteur spécique à XQBEL . Leur langage de prédilection est le XQuery,
toute requête XQBEL peut être traduite en une requête XQuery que l'on
peut alors executer sur un document XML.
Bibliographie
[1] Daniele Braga, Alessandro Campi, and Stefano Cerri. XQBE (XQuery
By Example) : a visual interface to the standard xml query language.
http ://www.acm.org/tods/accepted/2005/CampiXQBE.pdf.
[2] W3C group. Extensible markup language (xml) 1.0 (third edition).
http ://www.w3.org/TR/2004/REC-xml-20040204/.
[3] W3C group. Xml path language (xpath). http ://www.w3.org/TR/xpath.

[4] W3C group. Xml query (xquery). http ://www.w3.org/XML/Query.

[5] W3C group. Xsl transformations (xslt). http ://www.w3.org/TR/xslt.