Techniques à Objets et Internet - 2007

Programmation Web (J.-F. Perrot)

Un exemple d'exploitation multimodale d'un document XML :
le menu du restaurant


  1. Le document XML en question : fichier Menu/Menu.xml

  2. Affichage par le navigateur
    1. La transformation  XSLT vers HTML (fichier Menu/Menu.xsl)
    2. La feuille de style CSS (fichier Menu/Menu.css)
    3. Le code JavaScript qui engendre la date

  3. Le fichier PDF engendré
    1. La transformation XSLT vers FO (Formatting Objects)
    2. Mise en œuvre effective de la transformation vers PDF

  1. Le document XML en question : fichier Menu/Menu.xml


    <?xml version="1.0"  encoding="UTF-8"?>
    <?xml-stylesheet type="text/xsl" href="Menu.xsl"?>
    <liste>
    <étape nom="apéritif">
    <annonce>Vous boirez bien quelque chose ?</annonce>
    <choix>martini</choix>
    <choix>sauvignon</choix>
    <choix>whisky</choix>
    <choix>jus d'orange</choix>
    </étape>
    <étape nom="entrée">
    <annonce>Choisissez d'abord l'entrée</annonce>
    <choix> hareng</choix>
    <choix> salade </choix>
    <choix> œuf mimosa </choix>
    <choix> radis-beurre </choix>
    <choix> céleri rémoulade </choix>
    </étape>
    <étape nom="plat">
    <annonce>Choisissez ensuite votre plat principal</annonce>
    <choix> bifteck-frites</choix>
    <choix> blanquette de veau</choix>
    <choix> raie au beurre noir </choix>
    <choix> darne de saumon </choix>
    </étape>
    <étape nom="dessert">
    <annonce>Enfin, quel dessert vous ferait plaisir ?</annonce>
    <choix> fruits de saison </choix>
    <choix> crème glacée </choix>
    <choix> glace </choix>
    </étape>
    <étape nom="fin">
    <annonce>Bon appétit !</annonce>
    </étape>
    </liste>


  2. Affichage par le navigateur

    Lancement : Menu/AuRestaurant.php

    Affichage

    1. La transformation  XSLT vers HTML (fichier Menu/Menu.xsl)


      <?xml version='1.0'?>
      <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version='1.0'>

      <!-- ================== Pre'sentation du menu =================== -->

      <xsl:output method="html"/>
      <xsl:template match="/"> <!-- Le "cadre HTML -->
      <html>
      <head>
      <meta content="text/html; charset=UTF-8" http-equiv="content-type" />
      <title>Restaurant : le menu</title>
      <link rel="stylesheet" type="text/css" href="Menu.css"/>

      <script type="text/javascript" src="laDate.js" />
      </head>
      <body onload="faireLaDate();">

      <h2 id="date"> Menu du jour </h2>
      <xsl:apply-templates/>

      </body>
      </html>
      </xsl:template>

      <!-- ============ Traitement au niveau "étape" ============== -->

      <xsl:template match="liste/étape">
      <xsl:choose>
      <xsl:when test="@nom='apéritif'">
      <h3 id='apéritif'><i>Apéritifs</i></h3>
      </xsl:when>
      <xsl:when test="@nom='entrée'">
      <h3 id='entrée'><i>Les entrées</i></h3>
      </xsl:when>
      <xsl:when test="@nom='plat'">
      <h3 id='plat'><i>Les plats</i></h3>
      </xsl:when>
      <xsl:when test="@nom='dessert'">
      <h3 id='dessert'><i>Les desserts</i></h3>
      </xsl:when>
      </xsl:choose>
      <blockquote>
      <xsl:apply-templates select="./*"/>
      </blockquote>
      </xsl:template>

      <!-- ===== Traitement au niveau "intérieur à l'étape" ===== -->

      <xsl:template match="choix">
      <p><xsl:value-of select="."/></p>

      </xsl:template>


      <xsl:template match="annonce">
      <!-- ne rien faire -->
      </xsl:template>

      <!-- ==================== et c'est tout =================== -->

      </xsl:stylesheet>



    2. La feuille de style CSS (fichier Menu/Menu.css)


      /* Un style pour les menus..*/

      body { background : black;
      font-family : Arial,Helvetica,sans-serif;
      }

      h2 { color : red }

      h3 { color : yellow;
      font-weight : bold;
      font-size : 12pt;
      line-height : 14pt;
      }
      p { color : white;
      font-size : 10pt;
      line-height : 12pt;
      text-indent : 0.5in;
      }



    3. Le code JavaScript qui engendre la date

      et l'insère dans la page via DOM (fichier Menu/laDate.js)


      // Calculer la date du jour et l'afficher

      function faireLaDate () {
      var tabJours=["dimanche","lundi", "mardi", "mercredi", "jeudi", "vendredi",
      "samedi"];

      var tabMois=["janvier", "f\u00E9vrier", "mars", "avril", "mai", "juin",
      "juillet", "ao\u00FBt", "septembre", "octobre", "novembre", "d\u00E9cembre"];

      var aujourdHui = new Date();

      var leQuantieme = aujourdHui.getDate();
      var leJourDeLaSemaine = tabJours[aujourdHui.getDay()];
      var leMois = tabMois[aujourdHui.getMonth()];
      var lAnnee = aujourdHui.getFullYear();
      var lHeure = aujourdHui.getHours();

      var repas = lHeure<15?"d\u00E9jeuner":"d\u00EEner";

      var msg = "Menu du "+repas+", "
      + leJourDeLaSemaine+" "+ leQuantieme+" "+leMois+" "+lAnnee;

      var leTitre = document.getElementById("date");

      leTitre.replaceChild(document.createTextNode(msg), leTitre.firstChild);

      }



  3. Le fichier PDF engendré

    fichier VersPDF/menu.pdf

    en pdf


    1. La transformation XSLT vers FO (Formatting Objects)

      - fichier VersPDF/menu2pdf.xsl


      <?xml version='1.0'?>
      <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      xmlns:fo="http://www.w3.org/1999/XSL/Format"
      version='1.0'>
      <xsl:output method="xml" indent="yes" encoding="utf-8" />

      <xsl:template match="/">
      <fo:root>
      <fo:layout-master-set>
      <fo:simple-page-master master-name="menu"
      page-height="29.7cm"
      page-width="21cm"
      margin-top="1cm"
      margin-bottom="1cm"
      margin-left="1.5cm"
      margin-right="0.5cm">
      <fo:region-body margin-top="1cm" margin-bottom="0cm" column-count="1"/>
      <fo:region-before extent="3cm"/>
      <fo:region-after extent="1.5cm"/>
      </fo:simple-page-master>
      </fo:layout-master-set>

      <fo:page-sequence master-reference="menu">
      <fo:flow flow-name="xsl-region-body">

      <fo:block text-align="center">

      <fo:block font-size="24pt" font-weight="bold"
      space-before="12pt" space-after="12pt">
      <xsl:text>Menu</xsl:text>
      </fo:block>

      <xsl:apply-templates select="liste/étape[@nom !='fin']"/>

      </fo:block>

      </fo:flow>
      </fo:page-sequence>
      </fo:root>

      </xsl:template>

      <xsl:template match="étape">
      <fo:block keep-together="always">

      <fo:block font-size="14pt" font-weight="bold" font-style="italic"
      space-before="24pt" space-after="6pt">
      <xsl:value-of select="@nom"/>
      </fo:block>

      <xsl:apply-templates select="choix" />
      <!-- on saute l'annonce -->

      </fo:block>
      </xsl:template>

      <xsl:template match="choix">
      <fo:block space-before="6pt" space-after="6pt">
      <xsl:value-of select="."/>
      </fo:block>
      </xsl:template>

      </xsl:stylesheet>


    2. Mise en œuvre effective de la transformation vers PDF

      (en Java, pour changer un peu)
      fichier VersPDF/Menu2Pdf.java, qui nécessite l'installation de Apache-FOP.

      import org.w3c.dom.*;
      import org.xml.sax.*;

      import javax.xml.parsers.*;
      import javax.xml.transform.*;
      import javax.xml.transform.dom.*;
      import javax.xml.transform.sax.*;
      import javax.xml.transform.stream.*;

      import org.apache.fop.apps.*;

      import java.io.File;
      import java.io.FileOutputStream;
      import java.io.OutputStream;

      public class Menu2Pdf {

      public static void main(String[] args) {

      String fichIn = args[0]; // la source XML
      String fichFst = args[1]; // la "feuille de style" XSLT
      String fichOut = args[2]; // le fichier de sortie en PDF

      Driver driver = new Driver();
      driver.setRenderer(Driver.RENDER_PDF);

      try {
      OutputStream out = new FileOutputStream(fichOut);
      driver.setOutputStream(out);
      Result res = new SAXResult(driver.getContentHandler());

      DocumentBuilder parseur =
      DocumentBuilderFactory.newInstance().newDocumentBuilder();
      Document doc = parseur.parse(fichIn);
      DOMSource don = new DOMSource(doc);

      StreamSource fst = new StreamSource(new File(fichFst));
      Transformer tf =
      TransformerFactory.newInstance().newTransformer(fst);

      tf.transform(don, res);
      out.close();

      } catch (Exception e) {
      System.out.println("Erreur "+ e.getMessage());
      }
      } // main
      }//Menu2Pdf