Change the psud theme.
[hacks/simpleWebSlides.git] / xpi / xpi_07.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 et XSLT en Java</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_06.xhtml" class="sws-previous"/>
80     <div class="sws-slide sws-cover sws-option-nofooter">
81       <h1>XML et Programmation Internet</h1>
82       <h1>Cours 7</h1>
83       <a href="mailto:kn@lri.fr">kn@lri.fr</a>
84     </div>
85     <h1>Requêtes XPath en Java</h1>
86     <div class="sws-slide">
87       <h1>Moteur XPath en java</h1>
88       <p>L'API JAXP contient un moteur XPath 1.0 complet. Outre les
89       classes nécessaires au chargement de fichier et à la
90       manipulation du DOM (voir cours 6), il faut charger les éléments
91       du package <a><tt>javax.xml.xpath</tt></a>. Comme pour le reste
92       de JAXP, on passe par un <tt>XPathFactory</tt> pour créer une
93       nouvelle instance du moteur XPath.
94     </p>
95   </div>
96   <div class="sws-slide">
97     <h1>Exemple : packages</h1>
98     <code style="background:white;">  //Pour les documents et DOM
99   <kbd>import org.w3c.dom.*;
100   import javax.xml.namespace.QName;
101   import javax.xml.parsers.DocumentBuilder;
102   import javax.xml.parsers.DocumentBuilderFactory;</kbd>
103
104   //Pour le moteur XPath
105   <u>import javax.xml.xpath.XPathFactory;
106   import javax.xml.xpath.XPath;
107   import javax.xml.xpath.XPathConstants;</u>
108
109   <kbd>public class TestXPath {</kbd>
110   //Deux attributs pour contenir le moteur XPath et le document builder
111     <kbd>XPath xp_ = null;
112     DocumentBuilder db_ = null;</kbd>
113
114     </code>
115   </div>
116   <div class="sws-slide">
117     <h1>Exemple : constructeur</h1>
118     <code style="background:white;">  <kbd>public TestXPath () {
119     try {
120      DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
121      factory.setNamespaceAware(true);
122      db_ = factory.newDocumentBuilder();
123
124      <u>XPathFactory xf = XPathFactory.newInstance();
125      xp_ = xf.newXPath();</u>
126
127    } catch (Exception e) {</kbd>
128     //Peuvent être levées en cas d'erreur de création d'objet XPath
129     //DocumentBuilder, par exemple si des options passées sont
130     //non-supportées.
131 <kbd>    }
132   }</kbd>
133
134     </code>
135   </div>
136 <div class="sws-slide">
137     <h1>Exemple : méthode d'évaluation</h1>
138     <code style="background:white;">
139    <kbd>NodeList eval(String fichier, String chemin) throws Exception {
140
141    </kbd>//Création d'un DOM pour le fichier source<kbd>
142    Document doc = db_.parse(fichier);
143
144    <u>NodeList nl = (NodeList) xp_.evaluate(chemin,
145                                          doc,
146                                          XPathConstants.NODESET);</u>
147
148
149    }</kbd>
150
151 </code>
152 </div>
153 <div class="sws-slide">
154     <h1>Méthode <tt>XPath.evaluate()</tt></h1>
155 <p>La méthode <tt>XPath.evaluate(xpath, n, type)</tt> permet d'évaluer une
156   l'expression <a>xpath</a> (donnée sous-forme de chaîne de
157   caractères), à partir du nœud contexte <tt>n</tt> (qui doit
158   implémenter l'interface <a>Node</a>). Le résultat est de
159   type <a>typ</a>. La fonction renvoie un résultat de
160   type <s>Object</s>. L'argument <tt>typ</tt> peut avoir 5 valeurs
161   possibles, définies dans la class <tt>XPathConstants</tt> :
162 </p>
163 <ul>
164   <li><tt><u>XPathConstants.BOOLEAN</u></tt>: le résultat est de type java <tt>Boolean</tt></li>
165   <li><tt><u>XPathConstants.NUMBER</u></tt>: le résultat est de type java <tt>Double</tt></li>
166   <li><tt><u>XPathConstants.STRING</u></tt>: le résultat est de type java <tt>String</tt></li>
167   <li><tt><u>XPathConstants.NODE</u></tt>: le résultat est de type java <tt>Node</tt></li>
168   <li><tt><u>XPathConstants.NODESET</u></tt>: le résultat est de type java <tt>NodeList</tt></li>
169 </ul>
170 <p>En effet, une expression XPath peut avoir comme valeur un booléen,
171   un ensemble de noeuds ou une chaîne dépendant du <s>contexte</s> où
172   elle est utilisée. On peut demander à Jaxp d'évaluer la requête
173   XPath pour un certain contexte.
174 </p>
175 </div>
176   <div class="sws-slide">
177     <h1>Exemple </h1>
178     <code><kbd>  Document doc = ...
179   String chemin = <u>"//descendant::year[position () = 1]";</u>
180
181
182   </kbd>//Crée une NodeList à un élément<kbd>
183   <u>NodeList nl = (NodeList) xp_.evaluate(chemin, doc, XPathConstants.NODESET);</u>
184
185   </kbd>//Renvoie le nœud correspondant ou null<kbd>
186   <u>Node n = (Node) xp_.evaluate(chemin, doc, XPathConstants.NODE);</u>
187
188   </kbd>//Renvoie le double java correspondant à la valeur<kbd>
189   <u>Double d = (Double) xp_.evaluate(chemin, doc, XPathConstants.NUMBER);</u>
190
191   </kbd>//Renvoie la chaine java correspondant au texte<kbd>
192   <u>String s = (String) xp_.evaluate(chemin, doc, XPathConstants.STRING);</u>
193
194   </kbd>//Renvoie la valeur de vérité corresondant au chemin<kbd>
195   <u>Boolean b = (Boolean) xp_.evaluate(chemin, doc, XPathConstants.BOOLEAN);</u>
196 </kbd></code>
197 </div>
198 <div class="sws-slide">
199 <h1>La classe <tt>XPathExpression</tt></h1>
200 <p>Cette classe est similaire à l'utilisation
201   de <a>PreparedStatements</a> en JDBC.<br/>
202 <span class="sws-pause">Utilité ?</span>
203 <span class="sws-pause">compiler la requête XPath une fois pour toute
204   et donc éviter de re-parser la chaîne de caractère à chaque
205   appel. <br/>Exemple : </span>
206 </p>
207 <code>
208 <kbd>   <u>XPathExpression ex = xp_.compile("//movie/title");</u>
209
210    NodeList nl1 = (NodeList) ex.evaluate(doc1, XPathConstants.NODESET);
211    NodeList nl2 = (NodeList) ex.evaluate(doc2, XPathConstants.NODESET);
212    NodeList nl3 = (NodeList) ex.evaluate(doc3, XPathConstants.NODESET);
213    …
214 </kbd></code>
215
216 </div>
217 <h1>XSLT</h1>
218 <div class="sws-slide">
219 <h1> Applications de transformations XSLT </h1>
220 <p>Appliquer une transformation XSLT est une opération complexe à
221   cause des différentes combinaisons possibles :
222 </p>
223 <ul>
224 <li>Le fichier source (ex: <tt>movie.xml</tt>) peut être soit déjà
225   chargé comme un <tt>DOM</tt>, soit sous forme de fichier, soit sous
226   forme de chaîne de caractères,…</li>
227 <li>Le fichier destination (ex: <tt>resultat.xhtml</tt>) est
228   représenté par une <tt>DOM</tt> qui doit être
229   éventuellement <i>sérialisé</i> (i.e. retransformé en fichier XML).
230 </li>
231 <li>La transformation elle même (ex: <tt>style.xsl</tt>) peut être
232   sous forme diverse (fichier, URL, DOM, …)
233 </li>
234 <p>On a donc une série de classes d'encapsulation (<tt>Source</tt>,
235   …), de factory, …</p>
236 </ul>
237
238
239 </div>
240 <div class="sws-slide">
241 <h1>Création d'une transformation</h1>
242 <p>Pour créer une transformation XSLT, il faut les classes suivantes,
243   du package: <tt>javax.xml.transform</tt></p>
244 <code>
245   //La classe permettant d'appliquer une transformation XSLT
246   //ainsi que sa factory
247   <u>import javax.xml.transform.Transformer;
248   import javax.xml.transform.TransformerFactory;</u>
249
250   //La classe permettant de charger des transformations ou des
251   //arguments de transformation sous forme de fichiers
252   <u>import javax.xml.transform.stream.StreamSource;</u>
253
254   //La classe permettant de charger des documents ou transformations
255   //sous forme de nœuds DOM
256   <u>import javax.xml.transform.dom.DOMSource;</u>
257
258 </code>
259 </div>
260
261 <div class="sws-slide">
262   <h1>Exemple</h1>
263
264 <code>
265   <u>TransformerFactory tf = TransformerFactory.newInstance();</u>
266   //On crée un StreamSource à partir d'un nom de fichier contenant
267   //la feuille de style XSLT
268   <u>Transformer tr = tf.newTransformer(new StreamSource("style.xsl"));</u>
269 </code>
270
271 <p>Le code ci-dessus crée un objet de type <tt>Transformer</tt>
272   représentant la transformation XSLT se trouvant dans le fichier
273   <tt>style.xsl</tt>. <br/>
274   Si on avait chargé le fichier sous forme d'un
275   arbre DOM:
276 </p>
277 <code>  <kbd>Document style_xsl = … ;</kbd>//chargement de style.xsl
278
279   <u>TransformerFactory tf = TransformerFactory.newInstance();</u>
280   <u>Transformer tr = tf.newTransformer(new DOMSource(style_xsl));</u>
281
282 </code>
283
284 </div>
285 <div class="sws-slide">
286 <h1>La méthode <tt>Transformer.transform()</tt></h1>
287 <code>            transform(<u>Source</u> xmlSource, <u>Result</u> outputTarget)
288 </code>
289 <p>Les interfaces <tt>Source</tt> et <tt>Result</tt> permettent
290   d'abstraire le type de l'entrée et de la sortie. Ces dernières
291   peuvent être :</p>
292 <ul>
293   <li>Des objets DOM : <u>DOMSource</u> et <u>DOMResult</u> </li>
294   <li>Des objets d'entrée sortie de la bibliothèque java standard
295   (<tt>File</tt>, <tt>Input/OutputStream</tt>, <tt>Reader/Writer</tt>,
296   chaîne de caractère représentant un nom de fichier
297   : <u>StreamSource</u> et <u>StreamResult</u></li>
298 </ul>
299
300 </div>
301 <div class="sws-slide">
302 <h1>Exemple</h1>
303 <code>
304  //On applique le transformer associé à style.xsl
305  //sur le fichier movie et on écrit le résultat sur
306  //la sortie standard :
307
308  <u>tr.transform(new StreamSource("movies.xml"), new StreamResult(System.out));</u>
309 </code>
310 </div>
311 <div class="sws-slide">
312   <h1>Sérialisation</h1>
313   <p>La manière la plus simple de <i>sérialiser un document</i> est de
314   créer une transformation XSLT vide (i.e qui fait l'identité) et de
315   demander à ce que le résultat soit un fichier (ou la sortie
316   standard)</p>
317   <code>
318   <kbd>Document doc = …; </kbd>//l'objet DOM que l'on veut sauver dans un fichier
319   <u>Transformer tr = tf.newTransformer();</u>
320   <u>tr.transform(new DOMSource(doc),</u>
321                   <u>new StreamResult(new FileOutputStream("fichier.xml")));</u>
322   </code>
323 </div>
324 <h1><i>Streaming</i> avec SAX</h1>
325 <div class="sws-slide">
326   <h1><i>Streaming</i> ?</h1>
327   <p>Charger un document avec DOM permet d'accéder à l'arbre « en
328     entier » mais peut être couteux en mémoire (chaque nœud possède au
329     moins 4 pointeurs, 2 chaines de caractères, …). On veut pouvoir
330     effectuer certains types d'opération à la volée :
331   </p>
332   <ul class="sws-pause">
333     <li  class="sws-pause">Faire des statistiques sur les documents (compter le nombre
334     d'éléments, d'attributs, …)</li>
335     <li  class="sws-pause">Faire des transformations simples qui
336     préservent la structure (par exemple mettre les balises en
337     majuscules)</li>
338     <li  class="sws-pause">Valider vis à vis d'une DTD</li>
339     </ul>
340 </div>
341 <div class="sws-slide">
342 <h1>Programmation évènementielle</h1>
343 <p>Les parseurs SAX (Simple API for XML) reposent sur la programmation
344   évènementielle. Ils lisent le fichier d'entrée et génèrent un
345   certain nombre d'évènements, auxquels on peut réagir avec du code.
346   Les évènements sont :
347 </p>
348 <ul>
349   <li>Début de document</li>
350   <li>Fin de document </li>
351   <li>Ouverture de balise (avec le nom et la liste des attributs)</li>
352   <li>Fermeture de balise (avec le nom)</li>
353   <li>Élément texte</li>
354   <li>Commentaire </li>
355   <li>…</li>
356 </ul>
357 </div>
358 <div class="sws-slide">
359   <h1>L'API SAX</h1>
360 <code>
361 import javax.xml.parsers.*;
362 import org.xml.sax.*;
363 import org.xml.sax.helpers.*;
364 </code>
365 <p>On doit étendre la classe par <tt>DefaultHandler</tt></p>
366 </div>
367 <div class="sws-slide">
368 <h1><tt>DefaultHandler</tt></h1>
369 <code>
370  //le parseur a lu length caractères qui se trouvent dans
371  //ch à partir de la position start
372  void  <u>characters</u>(char[] ch, int start, int length)
373
374  //le parseur a détécté la fin de document
375  void  <u>endDocument</u>()
376
377  //le parseur a détecté la fin d'un élément
378  void  <u>endElement</u>(String uri, String localName, String qName)
379
380  //le parseur a détecté du texte « ignorable »
381  void  <u>ignorableWhitespace</u>(char[] ch, int start, int length)
382
383  //le parseur a détecté le début du document
384  void  <u>startDocument</u>()
385  //le parseur a detecté le début d'un élément
386  void  <u>startElement</u>(String uri,String localName, String qName,
387                            Attributes attributes)
388 </code>
389 <p><tt><u>Attributes</u></tt> est une classe auxiliaire qui permet de
390   connaître le nom, le nombre et les valeurs des attributs pour cette
391   balise.</p>
392 </div>
393
394 <div class="sws-slide">
395 <h1><tt>Handler</tt> personnalisé</h1>
396 <p>On étend la classe <tt>DefaultHandler</tt> : </p>
397 <code>
398 <u>class MyHandler extends DefaultHandler</u> {
399    private int nb_elems;
400    MyHandler() {
401      nb_elems = 0;
402    }
403     void  <u>startElement</u>(String uri,String localName, String qName,
404                            Attributes attributes)
405     throws SAXException {
406     nb_elems++;
407
408     }
409    int getNbElems() { return nb_elems; };
410 }
411
412 </code>
413
414 </div>
415 <div class="sws-slide">
416 <h1>Invocation du parseur</h1>
417 <p>On utilise (encore) une factory : </p>
418 <code>
419  public static void main(String[] args) {
420     …
421     SAXParserFactory spf = <u>SAXParserFactory.newInstance</u>();
422     spf.setNamespaceAware(true);
423     SAXParser saxParser = <u>spf.newSAXParser</u>();
424
425     MyHandler my = <kbd>new MyHandler()</kbd>;
426     XMLReader xmlReader = <u>saxParser.getXMLReader</u>();
427     xmlReader.<u>setContentHandler(my)</u>;
428     xmlReader.parse(filename);
429 }
430 </code>
431
432 </div>
433   </body>
434 </html>