.
authorKim Nguyễn <kn@lri.fr>
Wed, 22 Oct 2014 08:50:08 +0000 (10:50 +0200)
committerKim Nguyễn <kn@lri.fr>
Wed, 22 Oct 2014 08:50:08 +0000 (10:50 +0200)
themes/uPsud.css
xpi/xpi_07.xhtml [new file with mode: 0644]

index 0166527..46eea82 100644 (file)
@@ -289,4 +289,9 @@ u {
     color: #00486c;
     background: none;
     text-decoration: none;
+}
+
+kbd {
+    color: #393938;
+    font-family:inherit;
 }
\ No newline at end of file
diff --git a/xpi/xpi_07.xhtml b/xpi/xpi_07.xhtml
new file mode 100644 (file)
index 0000000..30ef14e
--- /dev/null
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
+>
+<html xmlns="http://www.w3.org/1999/xhtml" >
+  <head>
+    <title>XPath et XSLT en Java</title>
+
+    <meta http-equiv="Content-Type"
+          content="text/html; charset=utf-8" />
+    <meta name="copyright"
+          content="Copyright &#169; 2013 Kim Nguyễn" />
+
+    <!-- Load jQuery -->
+    <script src="../jquery-1.9.1.min.js" type="text/javascript" ></script>
+    <!-- Load the library -->
+    <script src="../simpleWebSlides.js" type="text/javascript" ></script>
+
+    <link rel="stylesheet" href="../simpleWebSlides.css" type="text/css"  media="all" />
+    <!-- Load a custom Theme, the class-element marks this style-sheet
+      a "theme" that can be swtiched dynamicaly -->
+    <link class="sws-theme" rel="stylesheet"  title="U-Psud style"  href="../themes/uPsud.css" type="text/css" />
+
+    <!-- Customize some templates and initialize -->
+    <style type="text/css">
+      .xml-tag { color: #00486c; }
+    </style>
+    <script type="text/javascript">
+      <![CDATA[
+      SWS.Config['sws-slide-change'] = SWS.Effects.slideChangeFadeOutIn;
+      SWS.Config['sws-object-deactivate'] =  SWS.Effects.objectDeactivateFadeOut;
+      SWS.Config['sws-object-activate'] = SWS.Effects.objectActivateFadeIn;
+
+      //Ensures that we load SWS at the very end, after MathJax has
+      //been initialized
+
+      $(window).load(function () {
+       $(".inline-xml").each(function(i, elem)
+      {
+      var jelem = $(elem);
+      var code = jelem.html();
+      code = code.replace ("<![CDATA" + "[", "").replace ("]" + "]>", "");
+      code = code.replace (/>/g, ">>>");
+      code = code.replace (/</g, "<span class='xml-tag'>&lt;");
+      code = code.replace (/>>>/g,"&gt;</span>");
+
+      jelem.html(code);
+      });
+  });
+
+      var checkSVG = function (o, i)
+      {
+            if (i >= 10 || SWS.Utils.isUndefined(o) || o == null) return;
+            var svg = o.getSVGDocument();
+            if (svg == null) {
+              setTimeout(function() { checkSVG(o, i+1); }, 200);
+            } else {
+         var alltext = $(svg).find("text");
+         alltext.css("font-family", "DIN");
+         alltext.css("font-size", "70%");
+
+            };
+      };
+      $(window).load(function() {
+      $("embed").ready(function() {
+         setTimeout(function() {
+         $("embed").each(function(i, o) { checkSVG(this,0);   });
+}, 1000);
+        });
+     });
+      $(window).load(SWS.Presentation.init);
+
+       ]]>
+
+    </script>
+
+  </head>
+  <body>
+    <a href="xpi_06.xhtml" class="sws-previous"/>
+    <div class="sws-slide sws-cover sws-option-nofooter">
+      <h1>XML et Programmation Internet</h1>
+      <h1>Cours 7</h1>
+      <a href="mailto:kn@lri.fr">kn@lri.fr</a>
+    </div>
+    <h1>Requêtes XPath en Java</h1>
+    <div class="sws-slide">
+      <h1>Moteur XPath en java</h1>
+      <p>L'API JAXP contient un moteur XPath 1.0 complet. Outre les
+      classes nécessaires au chargement de fichier et à la
+      manipulation du DOM (voir cours 6), il faut charger les éléments
+      du package <a><tt>javax.xml.xpath</tt></a>. Comme pour le reste
+      de JAXP, on passe par un <tt>XPathFactory</tt> pour créer une
+      nouvelle instance du moteur XPath.
+    </p>
+  </div>
+  <div class="sws-slide">
+    <h1>Exemple : packages</h1>
+    <code style="background:white;">  //Pour les documents et DOM
+  <kbd>import org.w3c.dom.*;
+  import javax.xml.namespace.QName;
+  import javax.xml.parsers.DocumentBuilder;
+  import javax.xml.parsers.DocumentBuilderFactory;</kbd>
+
+  //Pour le moteur XPath
+  <u>import javax.xml.xpath.XPathFactory;
+  import javax.xml.xpath.XPath;
+  import javax.xml.xpath.XPathConstants;</u>
+
+  <kbd>public class TestXPath {</kbd>
+  //Deux attributs pour contenir le moteur XPath et le document builder
+    <kbd>XPath xp_ = null;
+    DocumentBuilder db_ = null;</kbd>
+
+    </code>
+  </div>
+  <div class="sws-slide">
+    <h1>Exemple : constructeur</h1>
+    <code style="background:white;">  <kbd>public TestXPath () {
+    try {
+     DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+     factory.setNamespaceAware(true);
+     db_ = factory.newDocumentBuilder();
+
+     <u>XPathFactory xf = XPathFactory.newInstance();
+     xp_ = xf.newXPath();</u>
+
+   } catch (Exception e) {</kbd>
+    //Peuvent être levées en cas d'erreur de création d'objet XPath
+    //DocumentBuilder, par exemple si des options passées sont
+    //non-supportées.
+<kbd>    }
+  }</kbd>
+
+    </code>
+  </div>
+<div class="sws-slide">
+    <h1>Exemple : méthode d'évaluation</h1>
+    <code style="background:white;">
+   <kbd>NodeList eval(String fichier, String chemin) throws Exception {
+
+   </kbd>//Création d'un DOM pour le fichier source<kbd>
+   Document doc = db_.parse(fichier);
+
+   <u>NodeList nl = (NodeList) xp_.evaluate(chemin,
+                                         doc,
+                                         XPathConstants.NODESET);</u>
+
+
+   }</kbd>
+
+</code>
+</div>
+<div class="sws-slide">
+    <h1>Méthode <tt>XPath.evaluate()</tt></h1>
+<p>La méthode <tt>XPath.evaluate(xpath, n, type)</tt> permet d'évaluer une
+  l'expression <a>xpath</a> (donnée sous-forme de chaîne de
+  caractères), à partir du nœud contexte <tt>n</tt> (qui doit
+  implémenter l'interface <a>Node</a>). Le résultat est de
+  type <a>typ</a>. La fonction renvoie un résultat de
+  type <s>Object</s>. L'argument <tt>typ</tt> peut avoir 5 valeurs
+  possibles, définies dans la class <tt>XPathConstants</tt> :
+</p>
+<ul>
+  <li><tt><u>XPathConstants.BOOLEAN</u></tt>: le résultat est de type java <tt>Boolean</tt></li>
+  <li><tt><u>XPathConstants.NUMBER</u></tt>: le résultat est de type java <tt>Double</tt></li>
+  <li><tt><u>XPathConstants.STRING</u></tt>: le résultat est de type java <tt>String</tt></li>
+  <li><tt><u>XPathConstants.NODE</u></tt>: le résultat est de type java <tt>Node</tt></li>
+  <li><tt><u>XPathConstants.NODESET</u></tt>: le résultat est de type java <tt>NodeList</tt></li>
+</ul>
+<p>En effet, une expression XPath peut avoir comme valeur un booléen,
+  un ensemble de noeuds ou une chaîne dépendant du <s>contexte</s> où
+  elle est utilisée. On peut demander à Jaxp d'évaluer la requête
+  XPath pour un certain contexte.
+</p>
+</div>
+  <div class="sws-slide">
+    <h1>Exemple </h1>
+    <code><kbd>  Document doc = ...
+  String chemin = <u>"//descendant::year[position () = 1]";</u>
+
+
+  </kbd>//Crée une NodeList à un élément<kbd>
+  <u>NodeList nl = (NodeList) xp_.evaluate(chemin, doc, XPathConstants.NODESET);</u>
+
+  </kbd>//Renvoie le nœud correspondant ou null<kbd>
+  <u>Node n = (Node) xp_.evaluate(chemin, doc, XPathConstants.NODE);</u>
+
+  </kbd>//Renvoie le double java correspondant à la valeur<kbd>
+  <u>Double d = (Double) xp_.evaluate(chemin, doc, XPathConstants.NUMBER);</u>
+
+  </kbd>//Renvoie la chaine java correspondant au texte<kbd>
+  <u>String s = (String) xp_.evaluate(chemin, doc, XPathConstants.STRING);</u>
+
+  </kbd>//Renvoie la valeur de vérité corresondant au chemin<kbd>
+  <u>Boolean b = (Boolean) xp_.evaluate(chemin, doc, XPathConstants.BOOLEAN);</u>
+</kbd></code>
+</div>
+<div class="sws-slide">
+<h1>La classe <tt>XPathExpression</tt></h1>
+<p>Cette classe est similaire à l'utilisation
+  de <a>PreparedStatements</a> en JDBC.<br/>
+<span class="sws-pause">Utilité ?</span>
+<span class="sws-pause">compiler la requête XPath une fois pour toute
+  et donc éviter de re-parser la chaîne de caractère à chaque
+  appel. <br/>Exemple : </span>
+</p>
+<code>
+<kbd>   <u>XPathExpression ex = xp_.compile("//movie/title");</u>
+
+   NodeList nl1 = (NodeList) ex.evaluate(doc1, XPathConstants.NODESET);
+   NodeList nl2 = (NodeList) ex.evaluate(doc2, XPathConstants.NODESET);
+   NodeList nl3 = (NodeList) ex.evaluate(doc3, XPathConstants.NODESET);
+   …
+</kbd></code>
+
+</div>
+<h1>XSLT</h1>
+<div class="sws-slide">
+<h1> Applications de transformations XSLT </h1>
+<p>Appliquer une transformation XSLT est une opération complexe à
+  cause des différentes combinaisons possibles :
+</p>
+<ul>
+<li>Le fichier source (ex: <tt>movie.xml</tt>) peut être soit déjà
+  chargé comme un <tt>DOM</tt>, soit sous forme de fichier, soit sous
+  forme de chaîne de caractères,…</li>
+<li>Le fichier destination (ex: <tt>resultat.xhtml</tt>) est
+  représenté par une <tt>DOM</tt> qui doit être
+  éventuellement <i>sérialisé</i> (i.e. retransformé en fichier XML).
+</li>
+<li>La transformation elle même (ex: <tt>style.xsl</tt>) peut être
+  sous forme diverse (fichier, URL, DOM, …)
+</li>
+<p>On a donc une série de classes d'encapsulation (<tt>Source</tt>,
+  …), de factory, …</p>
+</ul>
+
+
+</div>
+<div class="sws-slide">
+<h1>Création d'une transformation</h1>
+<p>Pour créer une transformation XSLT, il faut les classes suivantes,
+  du package: <tt>javax.xml.transform</tt></p>
+<code>
+  //La classe permettant d'appliquer une transformation XSLT
+  //ainsi que sa factory
+  <u>import javax.xml.transform.Transformer;
+  import javax.xml.transform.TransformerFactory;</u>
+
+  //La classe permettant de charger des transformations ou des
+  //arguments de transformation sous forme de fichiers
+  <u>import javax.xml.transform.stream.StreamSource;</u>
+
+  //La classe permettant de charger des documents ou transformations
+  //sous forme de nœuds DOM
+  <u>import javax.xml.transform.dom.DOMSource;</u>
+
+</code>
+</div>
+
+<div class="sws-slide">
+  <h1>Exemple</h1>
+
+<code>
+  <u>TransformerFactory tf = TransformerFactory.newInstance();</u>
+  //On crée un StreamSource à partir d'un nom de fichier contenant
+  //la feuille de style XSLT
+  <u>Transformer tr = tf.newTransformer(new StreamSource("style.xsl"));</u>
+</code>
+
+<p>Le code ci-dessus crée un objet de type <tt>Transformer</tt>
+  représentant la transformation XSLT se trouvant dans le fichier
+  <tt>style.xsl</tt>. <br/>
+  Si on avait chargé le fichier sous forme d'un
+  arbre DOM:
+</p>
+<code>  <kbd>Document style_xsl = … ;</kbd>//chargement de style.xsl
+
+  <u>TransformerFactory tf = TransformerFactory.newInstance();</u>
+  <u>Transformer tr = tf.newTransformer(new DOMSource(style_xsl));</u>
+
+</code>
+
+</div>
+<div class="sws-slide">
+<h1>La méthode <tt>Transformer.transform()</tt></h1>
+<code>            transform(<u>Source</u> xmlSource, <u>Result</u> outputTarget)
+</code>
+<p>Les interfaces <tt>Source</tt> et <tt>Result</tt> permettent
+  d'abstraire le type de l'entrée et de la sortie. Ces dernières
+  peuvent être :</p>
+<ul>
+  <li>Des objets DOM : <u>DOMSource</u> et <u>DOMResult</u> </li>
+  <li>Des objets d'entrée sortie de la bibliothèque java standard
+  (<tt>File</tt>, <tt>Input/OutputStream</tt>, <tt>Reader/Writer</tt>,
+  chaîne de caractère représentant un nom de fichier
+  : <u>StreamSource</u> et <u>StreamResult</u></li>
+</ul>
+
+</div>
+<div class="sws-slide">
+<h1>Exemple</h1>
+<code>
+ //On applique le transformer associé à style.xsl
+ //sur le fichier movie et on écrit le résultat sur
+ //la sortie standard :
+
+ <u>tr.transform(new StreamSource("movies.xml"), new StreamResult(System.out));</u>
+</code>
+</div>
+<div class="sws-slide">
+  <h1>Sérialisation</h1>
+  <p>La manière la plus simple de <i>sérialiser un document</i> est de
+  créer une transformation XSLT vide (i.e qui fait l'identité) et de
+  demander à ce que le résultat soit un fichier (ou la sortie
+  standard)</p>
+  <code>
+  <kbd>Document doc = …; </kbd>//l'objet DOM que l'on veut sauver dans un fichier
+  <u>Transformer tr = tf.newTransformer();</u>
+  <u>tr.transform(doc, new StreamSource(new FileOutputStream("fichier.xml")));</u>
+  </code>
+</div>
+<h1><i>Streaming</i> avec SAX</h1>
+<div class="sws-slide">
+  <h1><i>Streaming</i> ?</h1>
+  <p>Charger un document avec DOM permet d'accéder à l'arbre « en
+    entier » mais peut être couteux en mémoire (chaque nœud possède au
+    moins 4 pointeurs, 2 chaines de caractères, …). On veut pouvoir
+    effectuer certains types d'opération à la volée :
+  </p>
+  <ul class="sws-pause">
+    <li  class="sws-pause">Faire des statistiques sur les documents (compter le nombre
+    d'éléments, d'attributs, …)</li>
+    <li  class="sws-pause">Faire des transformations simples qui
+    préservent la structure (par exemple mettre les balises en
+    majuscules)</li>
+    <li  class="sws-pause">Valider vis à vis d'une DTD</li>
+    </ul>
+</div>
+<div class="sws-slide">
+<h1>Programmation évènementielle</h1>
+<p>Les parseurs SAX (Simple API for XML) reposent sur la programmation
+  évènementielle. Ils lisent le fichier d'entrée et génèrent un
+  certain nombre d'évènements, auxquels on peut réagir avec du code.
+  Les évènements sont :
+</p>
+<ul>
+  <li>Début de document</li>
+  <li>Fin de document </li>
+  <li>Ouverture de balise (avec le nom et la liste des attributs)</li>
+  <li>Fermeture de balise (avec le nom)</li>
+  <li>Élément texte</li>
+  <li>Commentaire </li>
+  <li>…</li>
+</ul>
+</div>
+<div class="sws-slide">
+  <h1>L'API SAX</h1>
+<code>
+import javax.xml.parsers.*;
+import org.xml.sax.*;
+import org.xml.sax.helpers.*;
+</code>
+<p>On doit étendre la classe par <tt>DefaultHandler</tt></p>
+</div>
+<div class="sws-slide">
+<h1><tt>DefaultHandler</tt></h1>
+<code>
+ //le parseur a lu length caractères qui se trouvent dans
+ //ch à partir de la position start
+ void  <u>characters</u>(char[] ch, int start, int length)
+
+ //le parseur a détécté la fin de document
+ void  <u>endDocument</u>()
+
+ //le parseur a détecté la fin d'un élément
+ void  <u>endElement</u>(String uri, String localName, String qName)
+
+ //le parseur a détecté du texte « ignorable »
+ void  <u>ignorableWhitespace</u>(char[] ch, int start, int length)
+
+ //le parseur a détecté le début du document
+ void  <u>startDocument</u>()
+ //le parseur a detecté le début d'un élément
+ void  <u>startElement</u>(String uri,String localName, String qName,
+                           Attributes attributes)
+</code>
+<p><tt><u>Attributes</u></tt> est une classe auxiliaire qui permet de
+  connaître le nom, le nombre et les valeurs des attributs pour cette
+  balise.</p>
+</div>
+
+<div class="sws-slide">
+<h1><tt>Handler</tt> personnalisé</h1>
+<p>On étend la classe <tt>DefaultHandler</tt> : </p>
+<code>
+<u>class MyHandler extends DefaultHandler</u> {
+   private int nb_elems;
+   MyHandler() {
+     nb_elems = 0;
+   }
+    void  <u>startElement</u>(String uri,String localName, String qName,
+                           Attributes attributes)
+    throws SAXException {
+    nb_elems++;
+
+    }
+   int getNbElems() { return nb_elems; };
+}
+
+</code>
+
+</div>
+<div class="sws-slide">
+<h1>Invocation du parseur</h1>
+<p>On utilise (encore) une factory : </p>
+<code>
+ public static void main(String[] args) {
+    …
+    SAXParserFactory spf = <u>SAXParserFactory.newInstance</u>();
+    spf.setNamespaceAware(true);
+    SAXParser saxParser = <u>spf.newSAXParser</u>();
+
+    MyHandler my = <kbd>new MyHandler()</kbd>;
+    XMLReader xmlReader = <u>saxParser.getXMLReader</u>();
+    xmlReader.<u>setContentHandler(my)</u>;
+    xmlReader.parse(filename);
+}
+</code>
+
+</div>
+  </body>
+</html>