• Aucun résultat trouvé

Recherche de la concordance de motifs (pattern matching)

Nous venons de voir à quelle condition il y a concordance entre un nœud N et un motif, un nœud contexte C étant donné.

Nous allons maintenant voir comment le moteur XSLT effectue la recherche de concor- dance de motif, ou pattern matching.

Le problème est que dans ce processus, le nœud contexte C n’est plus donné : le but est alors précisément d’en trouver un.

Ce qui est donné, maintenant, c’est le motif et le nœud N ; charge au moteur XSLT de déterminer si le motif concorde avec ce nœud N.

Il peut prendre un nœud C au hasard dans l’arbre XML, et l’utiliser comme nœud con- texte dans l’évaluation du motif ; si cela donne la concordance du motif avec le nœud N en cours d’examen, c’est gagné, il a la réponse. Mais sinon, c’est toujours l’incertitude : peut-être qu’en choisissant un autre nœud C on aurait la concordance, mais peut-être qu’il n’existe aucun nœud dans l’arbre XML, qui pris comme nœud contexte, donne la concordance...

Comment savoir ?

Une première idée, évidente, consisterait à effectuer le test de concordance en explorant l’un après l’autre tous les nœuds de l’arbre, et en prenant à chaque fois le nœud courant comme nœud contexte pour évaluer le motif : dès que l’on a trouvé un nœud qui donne la concordance, on peut arrêter.

Le problème est que s’il n’y pas concordance, on ne le sait qu’après avoir testé infruc- tueusement chaque nœud de l’arbre ! Et même s’il y a concordance du motif avec le nœud N, on aura probablement commencé la série de tests avec des nœuds contexte très

éloignés du nœud N, avec une faible probabilité d’obtenir la concordance, à moins que le

motif soit vraiment très bizarre et compliqué, mettant en jeu des relations de parenté très

éloignées entre le nœud N et le nœud contexte qu’il fallait trouver...

En fait, tout le problème est là : pourquoi écrire des motifs très bizarres et compliqués ? Il ne faut pas oublier que le but, dans l’écriture d’un motif, est simplement de désigner un certain nœud, ou une famille de nœuds, sur lesquels on veut qu’une certaine règle s’applique.

Dans ces conditions, entre deux motifs qui pourraient également convenir, un simple et direct et un qui passe par le cousin de l’oncle du fils du frère, autant prendre le simple et direct.

D’où l’idée de restreindre a priori la région de l’arbre dans laquelle la recherche sera effectuée, ce qui bien sûr limitera le motif à des relations de parenté compatibles avec cette région.

Or, clairement, la région la plus favorable pour lancer une recherche à partir d’un nœud donné est celle qui est constituée des ancêtres de ce nœud. En effet, la remontée vers un parent ne laisse jamais aucun choix, alors que la descente vers un enfant donne autant de choix possibles qu’il y a d’enfants : la remontée vers les ancêtres s’apparente au simple parcours d’une liste linéaire, alors que la descente vers les enfants reste un processus

éminemment arborescent et récursif.

Si maintenant on veut que la recherche de concordance entre un motif et un nœud N donné ait une chance d’aboutir, alors qu’on limite a priori la recherche d’un nœud contexte convenable aux ancêtres de N , il est impératif que le motif ne fasse pas inter- venir d’autre axe de localisation que child::.

D’où la règle :

Examinons cela sur un exemple (figure 3-11) :

Contrainte des ancêtres

Un motif ne peut mentionner aucun axe de localisation, sauf child::. On verra (Syntaxe et contrainte pour un motif XSLT, page 98) que l’on peut quand même relaxer un peu cette contrainte, car il y a des axes (comme attribute:: ou namespace::) qui ne font pas de mal.

Figure 3-11 Recherche de concordance. 1 2 3 4 c a b d d Nœud N Motif child::a/child::b/child::c/child::d ./a/b/c/d 1 (vide) ./a/b/c/d 2 (vide) ./a/b/c/d 3 (vide) ./a/b/c/d 4

Cet exemple montre un arbre XML avec deux nœuds <d> et leurs ancêtres communs <b>, <c>, <a>. On suppose que l’un des deux nœuds <d> (en grisé sur la figure) est le nœud que l’on veut tester par rapport au motif suivant (exprimé en syntaxe longue) :

child::a/child::b/child::c/child::d

Puisque dans le processus de recherche de concordance de motif, on décide de se limiter aux nœuds ancêtres du nœud test, seuls les nœuds notés (1), (2), (3), (4), ..., etc. (jusqu’à la racine de l’arbre) vont être successivement choisis comme nœud contexte. En (1), l’évaluation du motif va renvoyer un ensemble de nœuds (node-set) vide, car le nœud <c> n’a aucun enfant <a>. On refait évidemment le même constat aux étapes (2) et (3). En (4), l’évaluation du motif renvoie un ensemble de nœuds constitué des deux éléments <d> ; cet ensemble contient le nœud test : la concordance est donc établie, et la recherche s’arrête.

Mais maintenant imaginons qu’un motif puisse mentionner des axes de localisation quel- conques, et pas seulement child::, et que l’on puisse écrire par exemple :

child::a/following::b/child::c/child::d

Arrivés à l’étape (2), nous ne pourrions plus nous permettre de remonter « bêtement » vers l’ancêtre suivant, puisqu’à coup sûr, nous irions à l’échec ; il nous faudrait aller explorer certains des frères, oncles et neveux de <b> (voir figure 2-10 à la section Repré- sentation graphique, page 50), et pour chacun d’eux remonter sa lignée d’ancêtres. Ayant vu l’intérêt qu’il peut y avoir (en terme d’efficacité) à limiter a priori la recherche de concordance de motifs à la seule lignée d’ancêtres du nœud test, il faut maintenant en examiner les conséquences sur le pouvoir expressif des motifs.

Mais qu’est-ce que le pouvoir expressif d’un motif ? Est-ce sa capacité à ratisser large, ou au contraire à discriminer finement ?

Il n’y a aucun doute que c’est sa capacité à discriminer finement ; un exemple de motif ne discriminant pas grand-chose serait child::node() : un tel motif concorde avec n’importe quel nœud de type element node, comment node, processing instruction node, ou text node (voir Modèle arborescent d’un document XML vu par XPath, page 30).

Autant dire que si on équipe une règle d’un tel motif, la règle s’appliquera partout ou presque dans le document XML ; il n’y a guère que la racine (qui est fille de rien1), les

attributs et les domaines nominaux qui ne seront pas concernés par cette règle.

On voit donc que le motif le plus « ramasse-tout » que l’on puisse écrire est compatible avec la contrainte des ancêtres.

Donc, si on avait du souci a se faire sur une diminution du pouvoir expressif d’un motif,

à cause de l’introduction de la contrainte des ancêtres, ce serait plutôt du côté d’une dimi-

nution de pouvoir discriminant qu’il faudrait regarder.

Mais en fait, il n’y a pas de problème : même s’il vérifie la contrainte des ancêtres, un motif peut rester très discriminant.

Reprenons l’exemple déjà vu pour illustrer le propos : <?xml version="1.0" encoding="UTF-8"?>

<Saison> <Concert>

<Organisation> Anacréon </Organisation>

<Date>Samedi 9 octobre 1999 <Heure> 20H30 </Heure> </Date> <Lieu>Chapelle des Ursules</Lieu>

</Concert> <Théâtre>

<Organisation> Masques et Lyres </Organisation>

<Date>Mardi 19 novembre 1999 <Heure> 21H </Heure> </Date> <Lieu>Salle des Cordeliers</Lieu>

</Théâtre> <Théâtre>

<Organisation> Masques et Lyres </Organisation>

<Date>Mercredi 20 novembre 1999 <Heure> 21H30 </Heure> </Date> <Lieu>Salle des Cordeliers</Lieu>

</Théâtre> </Saison>

Prenons le motif Heure : il n’est pas très discriminant, car trois éléments différents concordent avec ce motif. Mais le motif Concert/Date/Heure l’est beaucoup plus : un seul élément du document XML concorde avec ce motif. Il est vrai que c’est parce qu’il n’y a qu’un seul concert dans le fichier, et que le motif Théâtre/Date/Heure pourtant construit de la même façon, est un peu moins discriminant, avec deux éléments concor- dants.

Mais rien n’empêche, s’il le faut, de renforcer la discrimination en faisant intervenir un prédicat. Un prédicat, présent dans l’expression d’un motif, peut être aussi complexe qu’on le veut, car sa complexité n’a aucune influence sur la localisation d’un nœud contexte adéquat pour la recherche de concordance, localisation qui sera toujours limitée aux ancêtres du nœud test.

Le motif Théâtre/Date/Heure évalué sur le nœud contexte <Saison> donne en résultat un ensemble de deux nœuds : le nœud <Heure> 21H </Heure> et le nœud <Heure>21H30 </Heure>. Supposons que l’on veuille trouver un motif qui désigne uniquement l’une de ces deux heures ; supposons de plus que l’heure qui nous intéresse soit celle du mer- credi ; on peut alors exprimer que c’est une <Heure> enfant d’une <Date> dont le texte (i.e. child::text()) est une chaîne qui contient « Mercredi », cette <Date> étant elle- même enfant de <Théâtre>.

Ce qui donne le motif :

Théâtre/Date[contains(child::text(), "Mercredi")]/Heure

On voit donc qu’il n’y a pas de souci à se faire sur les capacités discriminantes des motifs, même s’ils respectent la contrainte des ancêtres.

Documents relatifs