Apprenez à utiliser une des API fondamentales en réalisant un programme Java.
Naviguez dans un document XML et modifiez-le.
On dispose du document XML :
<?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE zoo SYSTEM "zoo.dtd" [ <!ENTITY % notations SYSTEM "notations.ent"> %notations; <!ENTITY flipper.jpg SYSTEM "flipper.jpg" NDATA jpg> <!ENTITY oum.jpg SYSTEM "oum.jpg" NDATA jpg> <!ENTITY ecco.jpg SYSTEM "ecco.jpg" NDATA jpg> ]> <!-- Un petit Zoo avec quelques animaux --> <zoo> <info>Ouvert tous les jours de 8h00 à 19h00</info> <info><img src="nourrir.gif" />Il est <b>interdit</b> de nourrir les animaux€.</info> <aquarium> <mammifères-marins> <dauphins> <dauphin id="jhgtr13" photo="flipper.jpg" date-naissance="1997-4-1"> <nom>Flipper</nom> <sexe>M</sexe> <taille unité="cm">215</taille> <poids unité="kg">105</poids> </dauphin> <dauphin id="lkjh45" photo="ecco.jpg" date-naissance="2003-10-23"> <nom>Ecco</nom> <sexe>F</sexe> <taille unité="cm">202</taille> <poids unité="kg">98</poids> </dauphin> <dauphin id="kjlhy90" photo="oum.jpg" date-naissance="1996-12-25"> <nom>Oum</nom> <sexe>F</sexe> <!-- c'est mon préféré --> <taille unité="cm">295</taille> <poids unité="kg" status="mesure approximative">190<!-- il faut refaire la pesée --></poids> </dauphin> </dauphins> </mammifères-marins> <poissons> <sélaciens> <danger>Il est <b>interdit</b> de nager avec les requins.</danger> <requin id="plojk09" espèce="marteau" date-naissance="1998-6-5"> <nom>Oussama</nom> <sexe>M</sexe> <taille unité="cm">455</taille> <poids unité="kg">540</poids> <commentaire>A tendance a se jeter contre les murs <![CDATA[<<< marteau & cinglé !!! >>>]]> <!-- Il faudra bien le faire piquer un jour --> </commentaire> </requin> <requin id="vgyuh43" espèce="requin bleu" nom-savant="carcharias glaucus" date-naissance="2004-1-13"> <nom>Saddam</nom> <sexe>M</sexe> <taille unité="cm">355</taille> <poids unité="kg" status="">425</poids> </requin> </sélaciens> </poissons> </aquarium> </zoo>
et de sa DTD :
<?xml version="1.0" encoding="ISO-8859-1" ?> <!ENTITY nourrir.gif SYSTEM "nourrir.gif" NDATA gif> <!ENTITY % block "p | info | danger | attention"> <!ENTITY % inline "b | i | em | strong | stabilo | img"> <!ENTITY % attractions "aquarium?, vivarium?, enclos?, volière?"> <!ENTITY % animal "nom, sexe, taille, poids, commentaire?"> <!ENTITY % animal-attr " id ID #REQUIRED espèce CDATA #IMPLIED nom-savant CDATA #IMPLIED photo ENTITY #IMPLIED date-naissance CDATA #REQUIRED "> <!ENTITY % u-attr " unité CDATA #REQUIRED status CDATA #IMPLIED "> <!ELEMENT p (#PCDATA | %inline;)*> <!ELEMENT info (#PCDATA | %inline;)*> <!ELEMENT danger (#PCDATA | %inline;)*> <!ELEMENT attention (#PCDATA | %inline;)*> <!ELEMENT b (#PCDATA | %inline;)*> <!ELEMENT i (#PCDATA | %inline;)*> <!ELEMENT em (#PCDATA | %inline;)*> <!ELEMENT strong (#PCDATA | %inline;)*> <!ELEMENT stabilo (#PCDATA | %inline;)*> <!ELEMENT img EMPTY> <!ATTLIST img src ENTITY #REQUIRED> <!ELEMENT zoo ((%block;)*, %attractions;)> <!ELEMENT aquarium (mammifères-marins?, poissons?)> <!ELEMENT mammifères-marins (dauphins?, baleines?, orques?)> <!ELEMENT poissons (sélaciens?)> <!ELEMENT vivarium (serpents?, arachnéens?)> <!ELEMENT serpents (boas?)> <!ELEMENT arachnéens (mygales?)> <!ELEMENT enclos (primates?, fauves?)> <!ELEMENT primates (gorilles?, orangs-outans?)> <!ELEMENT fauves (tigres?, lions?)> <!ELEMENT volière (oiseaux-terrestres?, oiseaux-aquatiques?, rapaces?)> <!ELEMENT oiseaux-terrestres (autruches?)> <!ELEMENT oiseaux-aquatiques (pingouins?, manchots?)> <!ELEMENT rapaces (aigles?)*> <!ELEMENT dauphins (%block; | dauphin)+> <!ELEMENT dauphin (%animal;)> <!ATTLIST dauphin %animal-attr;> <!ELEMENT baleines (%block; | baleine)+> <!ELEMENT baleine (%animal;)> <!ATTLIST baleine %animal-attr;> <!ELEMENT orques (%block; | orque)+> <!ELEMENT orque (%animal;)> <!ATTLIST orque %animal-attr;> <!ELEMENT sélaciens (%block; | requin)+> <!ELEMENT requin (%animal;)> <!ATTLIST requin %animal-attr;> <!ELEMENT boas (%block; | boa)+> <!ELEMENT boa (%animal;)> <!ATTLIST boa %animal-attr;> <!ELEMENT mygales (%block; | mygale)+> <!ELEMENT mygale (%animal;)> <!ATTLIST mygale %animal-attr;> <!ELEMENT gorilles (%block; | gorille)+> <!ELEMENT gorille (%animal;)> <!ATTLIST gorille %animal-attr;> <!ELEMENT orangs-outans (%block; | orang-outan)+> <!ELEMENT orang-outan (%animal;)> <!ATTLIST orang-outan %animal-attr;> <!ELEMENT tigres (%block; | tigre)+> <!ELEMENT tigre (%animal;)> <!ATTLIST tigre %animal-attr;> <!ELEMENT lions (%block; | lion)+> <!ELEMENT lion (%animal;)> <!ATTLIST lion %animal-attr;> <!ELEMENT autruches (%block; | autruche)+> <!ELEMENT autruche (%animal;)> <!ATTLIST autruche %animal-attr;> <!ELEMENT pingoins (%block; | pingoin)+> <!ELEMENT pingoin (%animal;)> <!ATTLIST pingoin %animal-attr;> <!ELEMENT manchots (%block; | manchot)+> <!ELEMENT manchot (%animal;)> <!ATTLIST manchot %animal-attr;> <!ELEMENT aigles (%block; | aigle)+> <!ELEMENT aigle (%animal;)> <!ATTLIST aigle %animal-attr;> <!ELEMENT nom (#PCDATA)> <!ELEMENT sexe (#PCDATA)> <!ELEMENT taille (#PCDATA)> <!ATTLIST taille %u-attr;> <!ELEMENT poids (#PCDATA)> <!ATTLIST poids %u-attr;> <!ELEMENT commentaire (#PCDATA | %block;)*>
qui utilise une entité :
<?xml version="1.0" encoding="ISO-8859-1" ?> <!NOTATION jpg SYSTEM "images/jpeg"> <!NOTATION gif SYSTEM "images/gif">
Le document XML décrit les animaux d'un Zoo. On veut faire une visite médicale systématique des jeunes animaux du Zoo. Etudiez et comprenez la structure de l'instance.
Ecrivez un programme en Java avec JAXP qui ajoute
un attribut qui ait ce rôle pour les animaux de moins de 2 ans.
On n'utilisera pas Document#getElementsByTagName()
: on se forcera
à parcourir le document d'une manière récursive.
Dans un premier temps, on se contentera de modifier le DOM sans
enregistrer les modifications.
import java.io.*; import java.util.*; import java.text.*; import javax.xml.parsers.*; import javax.xml.transform.*; import javax.xml.transform.dom.*; import javax.xml.transform.stream.*; import org.w3c.dom.*; import org.xml.sax.*; public abstract class DomUpdate { // arbre XML private Document doc; // fichier produit en sortie private String output; // on parse le document XML public DomUpdate(String input, String output) throws ParserConfigurationException, SAXException, IOException { // on parse le document XML DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setValidating( true ); DocumentBuilder parser = factory.newDocumentBuilder(); doc = parser.parse( input ); this.output = output; } // on traverse tous les noeuds du document public void processNodeRecursively(Node node) throws Exception { performUpdates( node ); for (Node child = node.getFirstChild(); child != null; child = child.getNextSibling()) { processNodeRecursively(child); } } // on réalise des mises à jour abstract public void performUpdates(Node node) throws Exception; // on sérialise le document public void serialize() throws TransformerConfigurationException, TransformerException { TransformerFactory factory = TransformerFactory.newInstance(); Transformer transformer = factory.newTransformer(); Source source = new DOMSource( doc ); Result result = new StreamResult( output ); transformer.transform( source, result ); } static public void main(final String[] args) { try { DomUpdate zoo = new DomUpdate(args[0], args[1]) { // concrète implémentation de DomUpdate // qui cherche les animaux de moins d'un an // et leur ajoute la date de visite médicale private String DATE_NAISSANCE_ATTR = "date-naissance"; private DateFormat DATE_FORMAT = new SimpleDateFormat("y-M-d"); private Calendar TODAY = Calendar.getInstance(); private String DATE_VISITE_MEDICALE = args[2]; // le traitement à faire sur les éléments public void performUpdates(Node node) throws ParseException { if ( node.getNodeType() == Node.ELEMENT_NODE ) { Element elem = (Element) node; // sont concernés les éléments qui ont un attribut "date-naissance" if ( elem.hasAttribute( DATE_NAISSANCE_ATTR ) ) { // on récupère l'attribut String birthDate = elem.getAttribute( DATE_NAISSANCE_ATTR ); Calendar cal = new GregorianCalendar(); cal.setTime( DATE_FORMAT.parse( birthDate ) ); // on ajoute 1 an à la date de naissance pour comparer avec la date du jour cal.add(Calendar.YEAR, 1); if ( cal.after( TODAY ) ) { // l'animal est jeune : on le marque pour la visite médicale elem.setAttribute("visite-médicale", DATE_VISITE_MEDICALE); } } } } }; // on traverse le document zoo.processNodeRecursively( zoo.doc.getDocumentElement() ); // on sérialise le document zoo.serialize(); } catch (Exception e) { System.out.println("Usage :\n DomUpdate in.xml out.xml date"); e.printStackTrace(); } } }
Pour les opérations sur les dates, utiliser java.util.Calendar
et pour convertir une chaîne en date, utiliser java.text.SimpleDateFormat
.
DateFormat DATE_FORMAT = new SimpleDateFormat( ... ); Date date = DATE_FORMAT.parse( ... ); Calendar TODAY = Calendar.getInstance(); Calendar cal = new GregorianCalendar(); cal.setTime( ... ); // opérations et tests : cal.add( ... ); if ( cal.after( ... ) ) { // ... }
Pour sérialiser un document DOM, il suffit de le transformer en utilisant un Transformer qui réalise une copie d'une source DOM vers un flot de caractères.