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
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
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
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 (# )>
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
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
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
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
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.
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.
<x q b e>
<body>
< c a t a l o g>
<b o o k>
< s l i s t>
</ s l i s t >
</ b o o k>
<b o o k>
< s l i s t>
</ s l i s t >
</ b o o k>
</ c a t a l o g>
</ body>
<h e a d>
</ h e a d>
</ x q b e>
</ x q b e>
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.
3 <x q b e>
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>
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 >
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
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
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
14 }
15 </ x q b e>
Première amélioration :
l'ordre
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
4.2.3 Remarque
3 <x q b e>
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>
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 >
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
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
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
12 }
13 </ x q b e>
4.3.1 Explication
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.
3 <x q b e>
7 <x s l : i f t e s t =" / c a t a l o g [ b o o k
10 [ title [ . = $ x ] ] ] ">
11 < t i t l e>
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 >
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
10 [ t i t l e [.=$ x ] ] ]
11 return
13 }
14 </ x q b e>
Deuxième amélioration :
l'axe ancêtre-descendant
<x q b e>
< t i t l e>
</ 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 >
<x q b e>
where
$ doc // t i t l e [ d e s c e n d a n t : : t e x t ( ) [ . = $ x ] ]
return
</ x q b e>
<x q b e>
<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
</ 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 >
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
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 ">
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
8 </ x s l : t e x t >
9 <x q b e>
16 <x s l : v a r i a b l e name="
17 </ x s l : t e x 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 >
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 >
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 ( . , ' # ' ) ] ">
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 [
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 /
79
80 <! −− TRAITEMENT DES NOEUDS−TEXTE NON VARIABLES AVEC UNE LONGUEUR > 0 DE Q −−>
Chapitre 6 : Transformation d'une requête XQBE 39
84 </ x s l : t e x t >
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 ( . , ' # ' ) ] ">
98 </ x s l : t e x t >
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>
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 ">
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 ">
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
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.
16 <x s l : v a r i a b l e name="
17 </ x s l : t e x 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 >
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.
33 </ x s l : t e x t >
36 ">
37 </ x s l : t e x t >
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 ( . , ' # ' ) ] ">
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>
67 [
71 </ x s l : t e m p l a t e>
75 /
84 </ x s l : t e x t >
88 </ x s l : t e x t >
89 </ x s l : t e m p l a t e>
98 </ x s l : t e x t >
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 ">
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 ">
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.
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 [
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 [
25 </ x s l : i f >
26 </ x s l : t e m p l a t e>
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
2 [ descendant::
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 //
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 >
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 ( . , ' # ' ) ] ">
29 </ x s l : t e x t>
33 </ x s l : t e x t>
34 </ x s l : t e m p l a t e>
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 ">
4 <x q b e>
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 ( . , ' # ' ) ] ">
15 </ 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>
31 </ x s l : t e x t>
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 [
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 /
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 >
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 ( . , ' # ' ) ] ">
68 </ x s l : t e x t >
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 ( ) ">
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 ( . , ' # ' ) ] ">
88 </ x s l : t e x t >
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 >
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 [
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 [
25 </ x s l : i f >
26 </ x s l : t e m p l a t e>
2 [ descendant::
7 //
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 ">
14 [ d e s c e n d a n t : : t e x t ()[.=& apos ;
15 </ x s l : t e x t >
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 ">
27 </ x s l : t e x t >
31 </ x s l : t e x t >
32 </ x s l : t e m p l a t e>
Complexité du problème
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.
7.1.1 Démonstration
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.
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
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 .
À 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.
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