Add XPI lecture 3
[hacks/simpleWebSlides.git] / xpi / xpi_03.xhtml
1 <?xml version="1.0" encoding="utf-8" ?>
2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
3           "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
4 >
5 <html xmlns="http://www.w3.org/1999/xhtml" >
6   <head>
7     <title>XPath (suite)</title>
8
9     <meta http-equiv="Content-Type"
10           content="text/html; charset=utf-8" />
11     <meta name="copyright"
12           content="Copyright &#169; 2013 Kim Nguyễn" />
13
14     <!-- Load jQuery -->
15     <script src="../jquery-1.9.1.min.js" type="text/javascript" ></script>
16     <!-- Load the library -->
17     <script src="../simpleWebSlides.js" type="text/javascript" ></script>
18
19     <link rel="stylesheet" href="../simpleWebSlides.css" type="text/css"  media="all" />
20     <!-- Load a custom Theme, the class-element marks this style-sheet
21       a "theme" that can be swtiched dynamicaly -->
22     <link class="sws-theme" rel="stylesheet"  title="U-Psud style"  href="../themes/uPsud.css" type="text/css" />
23
24     <!-- Customize some templates and initialize -->
25     <style type="text/css">
26       .xml-tag { color: #00486c; }
27     </style>
28     <script type="text/javascript">
29       <![CDATA[
30       SWS.Config['sws-slide-change'] = SWS.Effects.slideChangeFadeOutIn;
31       SWS.Config['sws-object-deactivate'] =  SWS.Effects.objectDeactivateFadeOut;
32       SWS.Config['sws-object-activate'] = SWS.Effects.objectActivateFadeIn;
33
34       //Ensures that we load SWS at the very end, after MathJax has
35       //been initialized
36
37       $(window).load(function () {
38        $(".inline-xml").each(function(i, elem)
39       {
40       var jelem = $(elem);
41       var code = jelem.html();
42       code = code.replace ("<![CDATA" + "[", "").replace ("]" + "]>", "");
43       code = code.replace (/>/g, ">>>");
44       code = code.replace (/</g, "<span class='xml-tag'>&lt;");
45       code = code.replace (/>>>/g,"&gt;</span>");
46
47       jelem.html(code);
48       });
49   });
50
51       var checkSVG = function (o, i)
52       {
53             if (i >= 10 || SWS.Utils.isUndefined(o) || o == null) return;
54             var svg = o.getSVGDocument();
55             if (svg == null) {
56               setTimeout(function() { checkSVG(o, i+1); }, 200);
57             } else {
58          var alltext = $(svg).find("text");
59          alltext.css("font-family", "DIN");
60          alltext.css("font-size", "70%");
61
62             };
63       };
64       $(window).load(function() {
65       $("embed").ready(function() {
66          setTimeout(function() { 
67          $("embed").each(function(i, o) { checkSVG(this,0);   });
68 }, 1000);
69         });
70      });
71       $(window).load(SWS.Presentation.init);
72
73         ]]>
74
75     </script>
76
77   </head>
78   <body>
79     <a href="xpi_02.xhtml" class="sws-previous"/>
80     <div class="sws-slide sws-cover sws-option-nofooter">
81       <h1>XML et Programmation Internet</h1>
82       <h1>Cours 3</h1>
83       <a href="mailto:kn@lri.fr">kn@lri.fr</a>
84     </div>
85     <h1>Évaluation des prédicats</h1>
86     <div class="sws-slide">
87       <h1>Rappels de syntaxe</h1>
88 <code>
89       p ::=   p or p
90          |    p and p
91          |    not (p)
92          |    count(…), contains(…), position(), …
93          |    chemin XPath
94          |    e<sub>1</sub> op e<sub>2</sub>
95 </code>
96 <p>On évalue le prédicat et on converti son résultat en valeur de
97   vérité. Si la valeur vaut vrai, on garde le nœud courant, si elle
98   vaut faux, on ne le garde pas
99 </p>
100 <p>XPath connait <a>4 types de données</a> pour les prédicats : </p>
101 <ul>
102 <li>Les booléens, valeur de vérité : vrai ou faux</li>
103 <li>Les nombres (flottants), valeur de vérité compliquée… </li>
104 <li>Les chaînes de caractères, chaîne vide = faux, sinon vrai</li>
105 <li>Les ensembles de nœuds, ensemble vide = faux, sinon vrai </li>
106 </ul>
107     </div>
108 <div class="sws-slide">
109 <h1>Comparaisons (e<sub>1</sub> op e<sub>2</sub>)</h1>
110 <p> Les opérateurs de comparaisons sont : <tt>=, !=, &lt;, &lt;=,
111     &gt;, &gt;= </tt>.<br/>
112   La manière de calculer de vérité de <tt>e<sub>1</sub> op
113     e<sub>2</sub></tt> dépend du typed de <tt>e<sub>1</sub></tt>
114     et  <tt>e<sub>2</sub></tt> :
115 </p>
116 <ul>
117   <li>Si  <tt>e<sub>1</sub></tt> et  <tt>e<sub>2</sub></tt> représente
118     <a>des ensembles de nœuds</a>, alors la comparaison est vraie ssi
119     il existe un élément <tt>x</tt> dans <tt>e<sub>1</sub></tt> et un
120     élément <tt>y</tt> dans <tt>e<sub>2</sub></tt> tels que <tt>x&nbsp;op&nbsp;y</tt>
121   </li>
122
123   <li>Si  <tt>e<sub>1</sub></tt> représente
124     <a>un ensembles de nœuds</a> et <tt>e<sub>2</sub></tt> une valeur
125     scalaire <tt>y</tt>, alors la comparaison est vraie ssi
126     il existe un élément <tt>x</tt> dans <tt>e<sub>1</sub></tt> tel que <tt>x&nbsp;op&nbsp;y</tt>
127   </li>
128   <li>Si <tt>e<sub>1</sub></tt> et  <tt>e<sub>2</sub></tt> sont des
129   valeurs scalaires, alors ont les compare en utilisant les règles de
130   comparaison des valeurs scalaires (voir page suivante).
131   </li>
132 </ul>
133 </div>
134 <div class="sws-slide">
135 <h1>Comparaisons des valeurs scalaires</h1>
136 <code>                                  v<sub>1</sub> op v<sub>2</sub> </code>
137 <p>Si op est <tt>!=</tt> ou <tt>=</tt>, on applique les règles dans cet ordre:</p>
138 <ol>
139 <li> Si <tt>v<sub>1</sub></tt> (resp. <tt>v<sub>2</sub></tt>) est
140   un <a>booléen</a>, alors <tt>v<sub>2</sub></tt>
141   (resp. <tt>v<sub>1</sub></tt>) est converti en booléen et les deux
142   booléens sont comparés </li>
143 <li> Sinon si <tt>v<sub>1</sub></tt> (resp. <tt>v<sub>2</sub></tt>) est
144   un <a>nombre</a>, alors <tt>v<sub>2</sub></tt>
145   (resp. <tt>v<sub>1</sub></tt>) est converti en nombre et les deux
146   nombres sont comparés </li>
147 <li> Sinon, <tt>v<sub>1</sub></tt> et <tt>v<sub>2</sub></tt> sont des
148   <a>chaines de caractères</a>, on les compares</li>
149 </ol>
150 <p>Si op est <tt> &lt;</tt>,  <tt> &lt;=</tt>,  <tt> &gt;</tt> ou <tt>
151     &gt;=</tt>, on convertit <tt>v<sub>1</sub></tt>
152     et <tt>v<sub>2</sub></tt> en <a>nombres</a> et on les compare.
153 </p>
154 </div>
155 <div class="sws-slide">
156 <h1>Conversions</h1>
157 <p>Conversion en booléen</p>
158 <ul>
159   <li>0 et NaN sont converti en <tt>false</tt>, le reste
160   en <tt>true</tt> </li>
161   <li>Un ensemble de nœud vaut <tt>true</tt> ssi il est non vide</li>
162   <li>Une chaine vaut <tt>true</tt> ssi elle est non vide</li>
163 </ul>
164 <p>Conversion en nombre</p>
165 <ul>
166   <li>Une chaine de caractère représentant un flottant au format
167   IEEE-754 est convertie en ce nombre, sinon elle est convertie en NaN
168   </li>
169   <li>Booléen: <tt>true</tt> est converti à 1, <tt>false</tt> est
170   converti à 0</li>
171   <li>Un ensemble de nœud est d'abord converti en chaine de caractères
172   puis la chaine est convertie en nombre</li>
173 </ul>
174 </div>
175 <div class="sws-slide">
176 <h1>Conversions (suite)</h1>
177 <p>Conversion en chaine de caractères</p>
178 <ul>
179   <li>Un booléen est traduit en <tt>"true"</tt> ou <tt>"false"</tt>
180   selon sa valeur</li>
181   <li>Nombres:
182     <ul><li>NaN est converti en la chaine <tt>"NaN"</tt></li>
183       <li>Si le nombre n'a pas de partie décimale, sa
184       représentation <i>entière</i> est convertie en chaine (ex:
185       1.000e10 ≡ <tt>"10"</tt>)</li>
186       <li>Sinon une représentation IEE-754 du nombre est utilisé
187       (ex: <tt>"123.10e-34"</tt>)
188         </li>
189     </ul>
190   </li>
191   <li>Ensemble de noœud : <ul>
192       <li>L'ensemble vide est converti en la chaine vide
193       </li>
194       <li>Sinon le premier élément dans l'ordre du document est
195       converti en chaine en concatenant tous les nœuds textes dans ces
196       descendants (y compris lui-même)</li>
197     </ul>
198   </li>
199 </ul>
200 </div>
201
202 <div class="sws-slide">
203 <h1>Appels de fonction</h1>
204 <p>Il existe des fonctions prédéfinies (voir la spec XPath)</p>
205 <ul>
206   <li><tt>contains(str<sub>1</sub>,str<sub>2</sub>)</tt></li>
207   <li><tt>starts-with(str<sub>1</sub>,str<sub>2</sub>)</tt></li>
208   <li><tt>count(node_set<sub>1</sub>)</tt></li>
209   <li><tt>last()</tt></li>
210   <li><tt>position()</tt></li>
211   <li>…</li>
212 </ul>
213 <p>Si les arguments ne sont pas du bon type, ils sont convertis en
214   utilisant les règles de conversion</p>
215 </div>
216 <div class="sws-slide">
217 <h1>Exemples</h1>
218 <p>Dans la suite, on se donne un document de test ayant une
219   racine <tt><![CDATA[<a> ... </a>]]></tt> et une expression XPath qui
220   sélectionne la racine si et seulement si le prédicat vaut vrai
221 </p>
222 </div>
223 <div class="sws-slide">
224   <h1>Exemples</h1>
225   <code>        <![CDATA[ <a>
226            <b>1</b>
227            <c>2</c>
228          </a> ]]></code>
229 <ol> <li class="sws-pause">
230     <tt>/child::a[ child::*/child::text() ]</tt>
231     <span class="sws-pause">sélectionne la racine (l'ensemble de nœud
232     renvoyé par <tt>child::*/cild::text()</tt> est non vide, donc il est converti
233     en <tt>true</tt>)</span><br/><br/></li>
234  <li class="sws-pause">
235     <tt>/child::a[ child::*/child::text() = "2" ]</tt>
236     <span class="sws-pause">sélectionne la racine (l'ensemble de nœud texte
237     renvoyé par <tt>child::*/child::text()</tt> est comparé à "2", et
238     il existe un élément dans cet ensemble pour lequel le test réussi
239     )</span><br/><br/></li>
240   <li class="sws-pause"><tt>/child::a[ child::*/child::text() != "2" ]</tt>
241     <span class="sws-pause"><s>sélectionne la racine</s> (l'ensemble de nœud texte
242       renvoyé par <tt>child::*/child::text()</tt> est comparé à "2", et
243       il existe un élément dans cet ensemble pour lequel le test réussi
244       )</span><br/><br/></li>
245   <li class="sws-pause" style="background:white;"><tt>/child::a[ not(child::*/child::text() = "2") ]</tt>
246     <span class="sws-pause"><s>ne sélectionne pas la racine</s> (on
247       prend la négation du deuxième cas ci-dessus)
248     </span><br/><br/></li>
249
250 </ol>
251 </div>
252 <div class="sws-slide">
253   <h1>Exemples</h1>
254   <code>        <![CDATA[ <a>
255            <b>1</b><b>2</b>
256            <c>2</c><c>3</c>
257          </a> ]]></code>
258 <ol>
259  <li class="sws-pause">
260     <tt>/child::a[ child::*/child::text() &gt; 1.5 ]</tt>
261     <span class="sws-pause">sélectionne la racine (l'ensemble de nœud texte
262     renvoyé par <tt>child::*/child::text()</tt> est comparé à 1.5, et
263     il existe un élément dans cet ensemble pour lequel le test réussi
264     )</span><br/><br/></li>
265   <li class="sws-pause"><tt>/child::a[ child::b/child::text() &gt;= child::c/child::text() ]</tt>
266     <span class="sws-pause"><s>sélectionne la racine</s> (les deux
267       ensembles de nœuds sont convertis en ensmbles de nombres, car on
268       utilise <tt>&gt;=</tt> et on a bien que <tt>2 &gt;= 2</tt>
269       )</span><br/><br/></li>
270   <li class="sws-pause"><tt>/child::a[ child::b/child::text() = child::c/child::text() ]</tt>
271     <span class="sws-pause"><s>sélectionne la racine</s> (les deux
272       ensembles de nœuds comportent un élément commun)</span><br/><br/></li>
273   <li class="sws-pause"><tt>/child::a[ child::b/child::text() != child::c/child::text() ]</tt>
274     <span class="sws-pause"><s>sélectionne la racine</s> (les deux
275       comportent des éléments différents)</span><br/><br/></li>
276 </ol>
277 </div>
278 <div class="sws-slide">
279   <h1>Exemples</h1>
280   <code>                   <![CDATA[ <a><b>1</b><b>2</b><c>2</c><c>3</c></a> ]]></code>
281 <ol>
282  <li class="sws-pause">
283     <tt>/child::a[ contains(self::*, "22") ]</tt>
284     <span class="sws-pause"><s>sélectionne la racine</s>(l'ensemble de
285     nœud séléctionné par <tt>self::*</tt>, i.e. la racine est converti
286     en chaine. Pour ce faire, on colle toutes éléments textes
287     descendants et on obtient la chaine "1223" qui contient bien "22")
288     </span><br/><br/></li>
289  <li class="sws-pause">
290     <tt>/child::a[ self::* > 442.38 ]</tt>
291     <span class="sws-pause"><s>sélectionne la racine</s>(l'ensemble de
292     nœud séléctionné par <tt>self::*</tt>, est converti en chaine puis
293     en nombre pour comparer 1223 à 442.38)
294     </span><br/><br/></li>
295
296  <li class="sws-pause">
297     <tt>/child::a[ sum(child::*) &gt;= 7.5 ]</tt>
298     <span class="sws-pause"><s>sélectionne la racine</s>(la fonction
299     <tt>sum</tt> converti la liste de valeurs passée en argument en
300     liste de nombre et fait la somme de ces derniers)
301     </span><br/><br/></li>
302 </ol>
303 </div>
304
305 <div class="sws-slide">
306   <h1>Exemples</h1>
307   <code>                   <![CDATA[ <a><b>1</b><b>toto</b><c>2</c><c>3</c></a> ]]></code>
308 <ol>
309
310  <li class="sws-pause">
311     <tt>/child::a[ sum(child::*) &gt;= 7.5 ]</tt>
312     <span class="sws-pause"><s>ne sélectionne pas la racine</s>(la fonction
313     <tt>sum</tt> converti la liste de valeurs passée en argument en
314     liste de nombres, toto n'étant pas un nombre valide, il est
315     remplacé par NaN. La somme totale fait donc NaN, et une
316     comparaison avec NaN renvoie toujours faux)
317     </span><br/><br/></li>
318 </ol>
319 </div>
320 <div class="sws-slide">
321   <h1>Prédicat imbriqués</h1>
322   <p>On peut imbriquer des prédicats de manière arbitraire:</p>
323   <code>  Q<sub>1</sub> ≡ /child::a[ child::b[ count(descendant::c) &gt; 4 ] ] </code>
324   <p>Quelle différence avec :</p>
325   <code>  Q<sub>2</sub> ≡ /child::a[ count(child::b/descendant::c) &gt; 4 ] </code>
326   <p class="sws-pause">Il suffit de considérer le document :
327     <code> <![CDATA[ <a>
328       <b> <c/> <c/> <c/></b> 
329       <b> <c/> <c/> </b>
330   </a>
331       ]]></code>
332     <tt>Q<sub>1</sub></tt> <s>ne séléctionne rien</s> car il n'y a
333     aucun <tt>b</tt> ayant plus de 4
334     descendants <tt>c</tt>.<br/>     <tt>Q<sub>2</sub></tt> <s>séléctionne</s>
335     la racine car le nombre de descendants <tt>c</tt> de
336     nœuds <tt>b</tt> est plus grand que 4.
337 </p>
338 </div>
339 <div class="sws-slide">
340   <h1><tt>position()</tt> et <tt>last()</tt> </h1>
341   <p>La fonction <tt>position()</tt> renvoie la position du nœud au
342   sein de <a>l'ensemble de résultats en cours de filtrage</a>. Last
343   renvoie le nombre d'éléments dans cet ensemble (ou l'indice du
344   dernier élément). Les indices commencent à 1 :</p>
345   <code><![CDATA[    <a>
346       <b>AA</b>
347       <b>BB</b>
348       <b>CC</b>
349     </a>]]>
350
351     /child::a/child::b[ position() = 2 ]          (renvoie <![CDATA[<b>BB</b>]]>)
352     /child::a/child::b[ position() = last() ]     (renvoie <![CDATA[<b>CC</b>]]>)
353     /child::a/child::b[ position() mod 2 = 1 ]    (renvoie <![CDATA[<b>AA</b>
354                                                            <b>CC</b>]]>)
355 </code>
356 </div>
357 <h1>Axes complexes</h1>
358 <div class="sws-slide">
359   <h1>L'axe <tt>attribute::</tt></h1>
360   <p>Permet d'accéder aux attributs d'un élément.<s>Attention</s>, les
361     attributs ne font pas partie des fils ni des descendants!</p>
362     <code><![CDATA[    <a>
363       <b id="a1" v="x" >AA</b>
364       <b id="b2" v="y" >BB</b>
365       <b id="b3" v="z" >CC</b>
366     </a>]]>
367
368     /descendant::b[ attribute::* = "y" ]          (renvoie <![CDATA[<b …>BB</b>]]>)
369     /descendant::b[ attribute::id = "y" ]         (ne renvoie rien)
370 </code>
371 </div>
372 <div class="sws-slide">
373   <h1>Les axes <tt>preceding::</tt> et <tt>following::</tt></h1>
374   <p>L'axe <tt>preceding::</tt> selectionne tous les nœuds arrivant
375     avant le nœud courant et qui ne sont pas des ancetres de ce
376     dernier.</p>
377   <p>L'axe <tt>following::</tt> selectionne tous les nœuds arrivant
378     après le nœud courant et qui ne sont pas des descendants de ce dernier.</p>
379     <code style="background:white;"><![CDATA[    <a>
380       <b > <c/>
381            <d> <e/> </d>
382            <f ><g/></f>
383       </b>
384       <h/>
385       <i/>
386       <j> <k>
387           <l/> <m/> <n/>
388         </k>
389       </j>
390     </a>]]>
391
392     /descendant::m/preceding::* (séléctionne l, i, h, b, c, d, e, f, g)
393     /descendant::d/following::* (sélectionne h, i, j, k, l, m)
394 </code>
395 </div>
396 <div class="sws-slide">
397 <h1>Autres opérateurs</h1>
398 <p>On peut donner plusieurs prédicats à un chemin :
399 <code>
400  <s>/descendant::a [ descendant::b ]</s><a>[ position () &gt; 4 ]</a><span style="color:orange;">[ child::c ]</span>
401 </code>
402 Sélectionne l'ensemble des nœuds <s>A<sub>1</sub> ayant un
403   tag <tt>a</tt> et ayant un descendant <tt>b</tt></s>. Filtre
404   A<sub>1</sub> pour ne garder que <a>A<sub>2</sub>, l'ensemble des
405   nœuds de A<sub>1</sub> étant en position supérieure à
406   4</a>. <span style="color:orange;">Filtre A<sub>2</sub> pour ne
407   garder que les nœuds ayant un fils <tt>c</tt></span>.
408 </p>
409 <p>On peut prendre <a>l'union</a> de plusieurs chemins :</p>
410 <code>
411     /descendant::a/parent::b | /descendant::c/following-sibling::d
412 </code>
413 </div>
414 <h1>Syntaxe abrégée</h1>
415 <div class="sws-slide">
416 <h1>Abréviations</h1>
417 <p>XPath étant très <a>verbeux</a> il existe une syntaxe abrégée pour
418   les situations les plus courantes :</p>
419 <ul>
420   <li> un nom de tag <tt>foo</tt> est l'abréviation
421   de <tt>child::foo</tt>. Exemple : <code> /a/b/c ≡ /child::a/child::b/child::c</code>
422     <br/></li>
423   <li> un <tt>//</tt> est l'abréviation
424   de <tt>/descendant-or-self::node()/</tt>. Exemple :
425     <code> //a ≡ /descendant-or-self::node()/child::a </code>
426     Prend tous les nœuds du document (y compris le
427     nœud fictif <tt>#document</tt> et exécute <tt>child::a</tt> sur
428     cet ensemble.<br/></li>
429   <li> <tt> .. </tt> est un synonyme
430   pour <tt>parent::node()</tt> </li>
431   <li> <tt> @foo </tt> est un synonyme pour <tt>attribute::foo</tt>
432   </li>
433 </ul>
434   <p>Exemple :</p>
435   <code>    //book [ year &gt; 2005 ]/title
436   </code>
437
438 </div>
439   </body>
440 </html>