--- /dev/null
+<?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 © 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'><");
+ code = code.replace (/>>>/g,"></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>