XMLBeans : mapping XML - JavaBeans
Date de publication : 11/07/2008
Par
Celinio FERNANDES (Autres articles)
Le but de ce tutoriel est de présenter XMLBeans, une librairie de la fondation Apache.
I. Présentation
II. Schéma XML et DTD
III. Exemple
IV. Génération des classes
V. Génération d'un fichier XML
VI. Parsing d'un fichier XML
VII. XMLCursor
VIII.XQuery
IX. XPath
X. Liens
XI. Remerciements
I. Présentation
XMLBeans est un outil qui permet de faire du databinding Java/XML.
Il a été initié en 2003 par David Bau, de BEA, puis est devenu open source puisque cédé à la fondation Apache.
On peut télécharger la librairie sur http://xmlbeans.apache.org/
La version actuelle est 2.3.0.
Elle offre la possibilité de mapper un document XML en objets Javabeans.
Au lieu de parcourir un arbre DOM ou de faire de l'évènementiel avec SAX par exemple, on passe par des getters et setters.
On peut générer des fichiers XML à partir de classes Java, ou inversement, générer des objets Java (POJOs) à partir de fichiers
XML.
Les outils utilisés dans cet article sont :
Eclipse 3.4 Ganymede
Java 1.5
Altova XMLSpy version 2008
XMLBeans 2.3.0
Saxon 8.8 (fichier saxonb8-8j.zip), une implémentation open-source de XSLT 2.0 et XPath 2.0, et XQuery 1.0
II. Schéma XML et DTD
Il est nécessaire de faire quelques rappels rapides.
Une DTD (Document Type Definition) : une DTD permet de vérifier qu'un document XML est valide.
Il est valide s'il est conforme aux règles sémantiques définies dans la DTD.
Un schéma XML : aussi appelé XSD (XML Schema Definition), il est une alternative aux DTDs.
Validation via un Schéma XML
Vehicule1.xml :
<?xml version = "1.0" encoding = "UTF-8"?>
<vehicules xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation = "vehicule1.xsd" >
<nom>moto</nom>
<nombre>24</nombre>
<couleur>verte</couleur>
</vehicules>
A l'aide de XMLSpy (ou tout simplement d'un browser), on peut valider le fichier XML, par
rapport au schéma XML suivant.
Vehicule1.xsd :
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="vehicules">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="nom" type="xsd:string" maxOccurs="unbounded"/>
<xsd:element name="nombre" type="xsd:integer" maxOccurs="unbounded"/>
<xsd:element name="couleur" type="xsd:string" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
Validation via une DTD
Vehicule2.xml :
<?xml version = "1.0" encoding = "UTF-8"?>
<!DOCTYPE vehicules SYSTEM "vehicule2.dtd">
<vehicules>
<nom>moto</nom>
<nombre>24</nombre>
<couleur>verte</couleur>
</vehicules>
Vehicule2.dtd :
<!ELEMENT vehicules (nom, nombre, couleur)>
<!ELEMENT nom (#PCDATA)>
<!ELEMENT nombre (#PCDATA)>
<!ELEMENT couleur (#PCDATA)>
Les schémas XML présentent plusieurs avantages par rapport aux DTDs :
- une syntaxe XML
- possibilité de spécifier les types des données
- espace de nommage (namespace), ce qui implique que les règles pour définir certains éléments seront à un certain
endroit tandis que les règles pour valider
les règles pour définir d'autres éléments seront à un autre endroit.
III. Exemple
Pour ce tutoriel, je vais prendre comme exemple de base le cas d'un parc automobile qu'on peut découper de la façon
suivante :
parcAuto.xml :
<?xml version="1.0" encoding="UTF-8"?>
<parcautomobile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="D:\WORK\XML\parcAuto.xsd">
<vehicule modele="coupe">
<marque>
<nom>Renault</nom>
<puissance chevaux="8" vitessemax="280"/>
<nombre>18</nombre>
<couleur>noir</couleur>
</marque>
<marque>
<nom>Peugeot</nom>
<puissance chevaux="11" vitessemax="320"/>
<nombre>10</nombre>
<couleur>rouge</couleur>
</marque>
</vehicule>
<vehicule modele="berline">
<marque>
<nom>Mercedes</nom>
<puissance chevaux="10" vitessemax="330"/>
<nombre>9</nombre>
<couleur>gris</couleur>
</marque>
<marque>
<nom>BMW</nom>
<puissance chevaux="12" vitessemax="300"/>
<nombre>7</nombre>
<couleur>bleu</couleur>
</marque>
</vehicule>
</parcautomobile>
On peut automatiquement créer le Schéma XML grâce à XMLSpy :
parcAuto.xsd :
<?xml version="1.0" encoding="UTF-8"?>
<!--W3C Schema generated by XMLSpy v2008 rel. 2 sp1 (http://www.altova.com)-->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="vehicule">
<xs:complexType>
<xs:sequence>
<xs:element ref="marque" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="modele" use="required">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="berline"/>
<xs:enumeration value="coupe"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:complexType>
</xs:element>
<xs:element name="puissance">
<xs:complexType>
<xs:attribute name="vitessemax" use="required">
<xs:simpleType>
<xs:restriction base="xs:short">
<xs:enumeration value="280"/>
<xs:enumeration value="300"/>
<xs:enumeration value="320"/>
<xs:enumeration value="330"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="chevaux" use="required">
<xs:simpleType>
<xs:restriction base="xs:byte">
<xs:enumeration value="10"/>
<xs:enumeration value="11"/>
<xs:enumeration value="12"/>
<xs:enumeration value="8"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:complexType>
</xs:element>
<xs:element name="parcautomobile">
<xs:complexType>
<xs:sequence>
<xs:element ref="vehicule" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="nombre">
<xs:simpleType>
<xs:restriction base="xs:byte">
<xs:enumeration value="10"/>
<xs:enumeration value="18"/>
<xs:enumeration value="7"/>
<xs:enumeration value="9"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="nom">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="BMW"/>
<xs:enumeration value="Mercedes"/>
<xs:enumeration value="Peugeot"/>
<xs:enumeration value="Renault"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="marque">
<xs:complexType>
<xs:sequence>
<xs:element ref="nom"/>
<xs:element ref="puissance"/>
<xs:element ref="nombre"/>
<xs:element ref="couleur"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="couleur">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="bleu"/>
<xs:enumeration value="gris"/>
<xs:enumeration value="noir"/>
<xs:enumeration value="rouge"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:schema>
IV. Génération des classes
Pour utiliser XMLBeans, il faut définir la variable d'environnement XMLBEANS_HOME, elle pointe vers
le répertoire d'installation de XMLBeans.
On va créer les classes Java à partir du Schéma XML.
Pour cela, il y a 2 façons de faire. Soit on passe par l'utilitaire SCOMP, soit on utilise une tâche Ant xmlbean.
L'utilitaire SCOMP (Schema Compiler)
Dans une fenêtre DOS, on tape la commande scomp :

Après avoir ajouter XMLBEANS_HOME/bin dans le PATH (set PATH=%PATH%;%XMLBEANS_HOME%\bin\), on peut taper la commande suivante :
>scomp -src src -javasource 1.5 –out parcAuto.xsd
Note: pour éviter d'avoir un java.io.IOException, il faut modifier le script scomp.cmd en changeant la ligne suivante :
java -classpath "%cp%" org.apache.xmlbeans.impl.tool.SchemaCompiler %*
par
%JAVA_HOME%/bin/java -classpath "%cp%" org.apache.xmlbeans.impl.tool.SchemaCompiler %*
On obtient la hiérachie suivante :
D:\tutorielXMLBeans\
D:\tutorielXMLBeans\parcAuto.xsd
D:\tutorielXMLBeans\xmltypes.jar (contient les classes compilées et des fichiers XSB nécessaires à XMLBeans)
D:\tutorielXMLBeans\src (contient les interfaces et classes générées)
D:\tutorielXMLBeans\src\noNamespace (pas de namespace dans le Schema)
D:\tutorielXMLBeans\src\noNamespace\CouleurDocument.java
D:\tutorielXMLBeans\src\noNamespace\MarqueDocument.java (type complexe Marque)
D:\tutorielXMLBeans\src\noNamespace\NombreDocument.java
D:\tutorielXMLBeans\src\noNamespace\NomDocument.java
D:\tutorielXMLBeans\src\noNamespace\ParcautomobileDocument.java (element racine Parcautomobile)
D:\tutorielXMLBeans\src\noNamespace\PuissanceDocument.java
D:\tutorielXMLBeans\src\noNamespace\VehiculeDocument.java (type complexe Vehicule)
D:\tutorielXMLBeans\src\noNamespace\impl
D:\tutorielXMLBeans\src\noNamespace\impl\CouleurDocumentImpl.java
D:\tutorielXMLBeans\src\noNamespace\impl\MarqueDocumentImpl.java
D:\tutorielXMLBeans\src\noNamespace\impl\NombreDocumentImpl.java
D:\tutorielXMLBeans\src\noNamespace\impl\NomDocumentImpl.java
D:\tutorielXMLBeans\src\noNamespace\impl\ParcautomobileDocumentImpl.java
D:\tutorielXMLBeans\src\noNamespace\impl\PuissanceDocumentImpl.java
D:\tutorielXMLBeans\src\noNamespace\impl\VehiculeDocumentImpl.java
Il faut inclure le jar xmltypes.jar dans le CLASSPATH.
Tâche Ant xmlbean
Une tâche ANT existe pour compiler un fichier XSD en classe XMLBeans. Elle permet d'obtenir un fichier JAR
mais aussi le code source.
build.xml :
<?xml version="1.0" encoding="UTF-8" ?>
<project name="Tutoriel" default="xmlbean" basedir=".">
<property name="xmlbeans.home" value="." />
<property name="schema" value="schema/parcAuto.xsd" />
<property name="dest.jar" value="dest/tuto.jar" />
<path id="xmlbeans.path">
<fileset dir="${xmlbeans.home}/lib" includes="*.jar"/>
</path>
<taskdef name="xmlbean"
classname="org.apache.xmlbeans.impl.tool.XMLBean"
classpathref="xmlbeans.path"
/>
<target name="xmlbean">
<xmlbean schema="${schema}"
srcgendir="src"
destfile="${dest.jar}"
classpathref="xmlbeans.path" />
</target>
</project>
Après lancement de la tâche, on obtient la hiérarchie suivante dans Eclipse :
L'archive tuto.jar contient les fichiers XSB et est à mettre dans le build path du projet :
V. Génération d'un fichier XML
Grâce aux classes engendrées par XMLBeans, on peut manipuler les différents éléments XML comme des objets java Beans.
Chaque interface possède une classe factory avec une méthode statique newInstance() pour créer une instance du type de la classe.
Les valeurs fixes sont représentées avec des énumérations.
On valide par rapport au schéma XML l'instance nouvellement créée avec la méthode validate()
de l'interface XmlObject.
GenerationXML.java :
package com.developpez.tutoriel;
import java.io.File;
import java.io.IOException;
import noNamespace.ParcautomobileDocument;
import noNamespace.CouleurDocument.Couleur;
import noNamespace.MarqueDocument.Marque;
import noNamespace.NomDocument.Nom;
import noNamespace.ParcautomobileDocument.Parcautomobile;
import noNamespace.PuissanceDocument.Puissance;
import noNamespace.VehiculeDocument.Vehicule;
import noNamespace.VehiculeDocument.Vehicule.Modele;
import org.apache.xmlbeans.XmlOptions;
public class GenerationXML {
public static void main(String[] args) throws IOException
{
//parc est une instance du document XML
ParcautomobileDocument parc = ParcautomobileDocument.Factory.newInstance();
//ajout d'un tag Parcautomobile au document XML
Parcautomobile parcautomobile = parc.addNewParcautomobile();
// ajout d'un Vehicule au parc automobile
Vehicule vehicule1 = parcautomobile.addNewVehicule();
vehicule1.setModele(Modele.COUPE);
//Vehicule de modèle COUPE, 1ère marque
Marque marque1 = vehicule1.addNewMarque();
marque1.setNom(Nom.RENAULT);
Puissance puissance1 = Puissance.Factory.newInstance();
puissance1.setChevaux((byte)8);
puissance1.setVitessemax((short)280);
marque1.setPuissance(puissance1);
marque1.setNombre((byte)18);
marque1.setCouleur(Couleur.NOIR);
//Vehicule de modèle COUPE, 2ème marque
Marque marque2 = vehicule1.addNewMarque();
marque2.setNom(Nom.PEUGEOT);
Puissance puissance2 = Puissance.Factory.newInstance();
puissance2.setChevaux((byte)11);
puissance2.setVitessemax((short)320);
marque2.setPuissance(puissance2);
marque2.setNombre((byte)10);
marque2.setCouleur(Couleur.ROUGE);
// ajout d'un Vehicule au parc automobile
Vehicule vehicule2 = parcautomobile.addNewVehicule();
vehicule2.setModele(Modele.BERLINE);
//Vehicule de modèle COUPE, 1ère marque
Marque marque3 = vehicule2.addNewMarque();
marque3.setNom(Nom.MERCEDES);
Puissance puissance3 = Puissance.Factory.newInstance();
puissance3.setChevaux((byte)10);
puissance3.setVitessemax((short)330);
marque3.setPuissance(puissance3);
marque3.setNombre((byte)9);
marque3.setCouleur(Couleur.GRIS);
//Vehicule de modèle COUPE, 2ème marque
Marque marque4 = vehicule2.addNewMarque();
marque4.setNom(Nom.BMW);
Puissance puissance4 = Puissance.Factory.newInstance();
puissance4.setChevaux((byte)12);
puissance4.setVitessemax((short)300);
marque4.setPuissance(puissance4);
marque4.setNombre((byte)7);
marque4.setCouleur(Couleur.BLEU);
// Validation de l'instance du schema XML
boolean estValide = parc.validate();
if (! estValide){
System.err.println("Attention, cette instance du schema n'est pas valide ! ");
return;
}
XmlOptions opts = new XmlOptions();
//cette option permet d'indenter le code
opts.setSavePrettyPrint();
System.out.println(parc.xmlText(opts));
parc.save(new File ("d:/parcAuto.xml"), opts);
}
}
On obtient en sortie un fichier XML parcAuto.xml identique au précédent.
VI. Parsing d'un fichier XML
Et inversement, il est possible de parcourir un fichier XML de façon totalement objet.
On utilise la méthode parse() de l'interface ParcautomobileDocument pour charger le fichier
et ensuite le parcourir.
ParseXML.java :
package com.developpez.tutoriel;
import java.io.File;
import noNamespace.ParcautomobileDocument;
import noNamespace.MarqueDocument.Marque;
import noNamespace.ParcautomobileDocument.Parcautomobile;
import noNamespace.PuissanceDocument.Puissance;
import noNamespace.VehiculeDocument.Vehicule;
public class ParseXML {
public static void main(String[] args) throws Exception
{
//Parsing du fichier XML
ParcautomobileDocument Parcautomobile = ParcautomobileDocument.Factory.parse(new File ("d:/parcAuto.xml"));
Parcautomobile parc = Parcautomobile.getParcautomobile();
//modelesVehicule est un tableau d'objets Vehicule
Vehicule[] modelesVehicule = parc.getVehiculeArray();
System.out.println("Nombre de modeles de vehicules: " + modelesVehicule.length);
// Version java 1.5
//parcours de tous les modèles de vehicule
for (Vehicule v : modelesVehicule){
System.out.println(v.getModele());
//parcours de toutes les marques de chaque modèle de vehicule
Marque[] lesMarques = v.getMarqueArray();
for (Marque m : lesMarques){
System.out.println(m.getNom()+ " " + m.getCouleur() + " " + m.getNombre());
Puissance puissance = m.getPuissance();
System.out.println(puissance.getChevaux()+ " " + puissance.getVitessemax());
}
System.out.println();
}
// Version java 1.4
//parcours de tous les modèles de vehicule
/*
for (int i=0; i<modelesVehicule.length; i++)
{
Vehicule modeleVehicule = parc.getVehiculeArray(i);
System.out.println(modeleVehicule.getModele());
for (int j=0; j<modeleVehicule.getMarqueArray().length; j++)
{
//parcours de toutes les marques de chaque modèle de vehicule
Marque marque = modeleVehicule.getMarqueArray(j);
System.out.println(marque.getNom()+ " " + marque.getCouleur() + " " + marque.getNombre());
Puissance puissance = marque.getPuissance();
System.out.println(puissance.getChevaux()+ " " + puissance.getVitessemax());
}
System.out.println();
}
*/
}
}
Sortie de la console :
Nombre de modeles de vehicules: 2
coupe
Renault noir 18
8 280
Peugeot rouge 10
11 320
berline
Mercedes gris 9
10 330
BMW bleu 7
12 300
VII. L'interface XMLCursor
L'interface XmlCursor fournit une navigation efficace dans un arbre XML, à la manière d'un curseur en PL/SQL.
Le curseur représente un endroit spécifique (noeud) dans le document XML.
Dans l'API XMLCursor, un document XML est constitué par des tokens.
Concrètement, un token est soit un type d'attribut, soit un début d'élément, soit une fin d'élément etc.
Exemple: on peut insérer un nouveau modèle de véhicule au niveau de l'élément racine <parcautomobile> , au tout début.
InsertionXML.java :
package com.developpez.tutoriel;
import java.io.File;
import noNamespace.ParcautomobileDocument;
import org.apache.xmlbeans.XmlCursor;
import org.apache.xmlbeans.XmlOptions;
public class InsertionXML {
public static void main(String[] args) throws Exception
{
//Parsing du fichier XML
ParcautomobileDocument Parcautomobile = ParcautomobileDocument.Factory.parse(new File ("d:/parcAuto.xml"));
// On se positionne au début du document XML
XmlCursor filtreCursor = Parcautomobile.newCursor();
filtreCursor.toNextToken();
filtreCursor.toNextToken();
filtreCursor.beginElement("vehicule");
// On ajoute un attribut modele sur l'element vehicule, avec la valeur sport.
filtreCursor.insertAttributeWithValue("modele", "sport");
filtreCursor.beginElement("marque");
filtreCursor.beginElement("nom");
filtreCursor.insertChars("Ferrari");
filtreCursor.toNextToken();
filtreCursor.beginElement("puissance");
filtreCursor.insertAttributeWithValue("chevaux", "18");
filtreCursor.insertAttributeWithValue("vitessemax", "400");
filtreCursor.toNextToken();
filtreCursor.beginElement("nombre");
filtreCursor.insertChars("3");
filtreCursor.toNextToken();
filtreCursor.beginElement("couleur");
filtreCursor.insertChars("jaune");
filtreCursor.dispose();
XmlOptions opts = new XmlOptions();
//cette option permet d'indenter le code
opts.setSavePrettyPrint();
System.out.println(Parcautomobile.xmlText(opts));
Parcautomobile.save(new File ("d:/parcAuto2.xml"), opts);
}
}
Résultat de l'insertion :
<?xml version="1.0" encoding="UTF-8"?>
<parcautomobile>
<vehicule modele="sport">
<marque>
<nom>Ferrari</nom>
<puissance chevaux="18" vitessemax="400"/>
<nombre>3</nombre>
<couleur>jaune</couleur>
</marque>
</vehicule>
<vehicule modele="coupe">
<marque>
<nom>Renault</nom>
<puissance chevaux="8" vitessemax="280"/>
<nombre>18</nombre>
<couleur>noir</couleur>
</marque>
<marque>
<nom>Peugeot</nom>
<puissance chevaux="11" vitessemax="320"/>
<nombre>10</nombre>
<couleur>rouge</couleur>
</marque>
</vehicule>
<vehicule modele="berline">
<marque>
<nom>Mercedes</nom>
<puissance chevaux="10" vitessemax="330"/>
<nombre>9</nombre>
<couleur>gris</couleur>
</marque>
<marque>
<nom>BMW</nom>
<puissance chevaux="12" vitessemax="300"/>
<nombre>7</nombre>
<couleur>bleu</couleur>
</marque>
</vehicule>
</parcautomobile>
VIII. XQuery
Pour une recherche avancée dans le document XML, on doit passer par XQuery.
XQuery est à XML ce que SQL est aux bases de données.
Si on veut récupérer dans le document XML le nombre de Peugeot dans le parc automobile,
on peut naviguer dans l'arbre pour aller se positionner
directement sur le sous-élément <nombre> de
l'élément <marque> , lui-même sous-élément de l'élément <vehicule modele="coupe">.
La méthode execQuery(queryExpression) de l'interface XmlCursor prend en paramètre une expression XQuery.
Note: il est nécessaire d'installer la librairie Saxon (processor XSLT et XQuery).
En effet, pour des raisons d'incompatibilités de licences, cette librairie n'est malheureusement pas incluse dans XMLBeans.
InsertionXML.java :
package com.developpez.tutoriel;
import java.io.File;
import noNamespace.ParcautomobileDocument;
import org.apache.xmlbeans.XmlCursor;
public class XqueryXML {
public static void main(String[] args) throws Exception
{
//Parsing du fichier XML
ParcautomobileDocument parcautomobile = ParcautomobileDocument.Factory.parse(new File ("d:/parcAuto.xml"));
// Avec une boucle FOR
String expression1 =
"for $e in //parcautomobile/vehicule/marque " +
"where $e/nom = 'Peugeot' " +
"return $e//nombre";
XmlCursor monCursor1 = parcautomobile.newCursor().execQuery(expression1);
System.out.println(monCursor1.getObject().toString());
System.out.println("Expression 1 : le nombre de vehicules de marque Peugeot est : " + monCursor1.getTextValue());
// En une seule ligne
String expression2 = " //parcautomobile/vehicule/marque[nom='Peugeot']/nombre ";
XmlCursor monCursor2 = parcautomobile.newCursor().execQuery(expression2);
System.out.println(monCursor2.getObject().toString());
System.out.println("Expression 2 : le nombre de vehicules de marque Peugeot est : " + monCursor2.getTextValue());
}
}
Résultat :
10
Expression 1 : le nombre de vehicules de marque Peugeot est : 10
10
Expression 2 : le nombre de vehicules de marque Peugeot est : 10
IX. XPath
On peut passer par des expressions XPath, que l'on donne en paramètre de la méthode selectPath(String).
Elle retourne des sélections.
Et on navigue ensuite à l'aide de la méthode toNextSelection(), pour itérer à travers les sélections.
Exemple : afficher tous les noms de marque de vehicules dans le fichier XML.
XpathXML.java :
package com.developpez.tutoriel;
import java.io.File;
import noNamespace.ParcautomobileDocument;
import org.apache.xmlbeans.XmlCursor;
public class XpathXML {
public static void main(String[] args) throws Exception
{
//Parsing du fichier XML
ParcautomobileDocument Parcautomobile = ParcautomobileDocument.Factory.parse(new File ("d:/parcAuto.xml"));
XmlCursor monCursor = Parcautomobile.newCursor();
monCursor.toFirstChild();
monCursor.push();
monCursor.selectPath("$this//nom");
//Afficher tous les noms de marque
while (monCursor.toNextSelection()) {
System.out.println(monCursor.getTextValue());
}
}
}
Résultat de la recherche :
Renault
Peugeot
Mercedes
BMW
X. Liens
XI. Remerciements
Je tiens à remercier gifffftane, Ricky81 pour les conseils, remarques et relectures, ainsi que diogene pour la correction orthographique.
Je remercie aussi www.developpez.com me permettant de publier cet article et Nono40 pour ses outils.
Copyright © Celinio FERNANDES. Aucune reproduction, même partielle, ne peut être
faite de ce site et de l'ensemble de son contenu : textes, documents, images,
etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi
jusqu'à 3 ans de prison et jusqu'à 300 000 Euros de dommages et intérets.
|