XML, DTD et structure Travaux Pratiques

Inria

Apprenez à maîtriser la syntaxe XML : un petit exercice plus difficile qu'il n'y paraît.

Concevez une instance XML et sa DTD. Créez un petit bout de code pour analyser votre document.

Prérequis

  • Connaître HTML peut aider
  • Savoir écrire une classe Java

Cours

  • XML et DTD

Syntaxe XML et structuration de l'information

Mise en jambe : le jeu des 16 erreurs

Notre ami Forrest a décidé d'écrire ses mémoires en XML. Aidez-le à corriger son document en conservant la structure logique et le contenu autant que faire se peut.

Forrest : sa vie, son oeuvre

Le fichier tp/xml/forrest.xml ne s'affichera pas dans votre navigateur car il contient des erreurs. Enregistrez-le, corrigez-le, et utilisez le parseur intégré à votre navigateur préféré pour vous aider.

Ci-dessous son contenu lu avec un décodage iso-8859-1 :

  1. <?xml version="1.0" encoding="UTF-8" standalone="standalone"?>
  2. <?xml-stylesheet type="text/xsl" href="fg.xsl"?>
  3. <!-- à relire -->
  4. <?robots index="yes" follow="no"?>
  5. <document>
  6. <titre style="bold" style="big">Mes mémoires</titre>
  7. <auteur>
  8. <nom>Gump</nom>
  9. <prénom>Forrest</prénom>
  10. <auteur>
  11. <description xmlns="http://www.w3.org/1999/xhtml"
  12. style="bold" Style="big" xml:space="preserve">
  13. <!-- à partir d'ici, on peut utiliser
  14. des éléments HTML <!-- et d'autres aussi -->
  15. c'est pratique pour du contenu
  16. documentaire -->
  17. <p xml:space="default" align=center>Ma maman disait
  18. toujours : &#xA; "<i>la vie c'est comme une
  19. bo&icirc;te de <b>chocolat</i>, on ne sait jamais
  20. sur quoi on va tomber</b>".</p>
  21. <hr width/>
  22. <a xlink:href="bubbagump.avi"
  23. xmlns:xlink="http://www.w3.org/1999/xlink"
  24. href="bubbagump.avi"
  25. xlink:role="mon film">
  26. <object xmlns:xlink=""
  27. xlink:href="bubbagump.avi"/>
  28. </a>
  29. <script language="JavaScript">
  30. <![CDATA[
  31. function check() {
  32. for (int i=10; i>0; i++) {
  33. if ( a[b[i]]>5 ) break;
  34. }
  35. }
  36. ]]>
  37. <!-- vérifier si la boucle doit scrire
  38. avec i-- et pas i++ -->
  39. </script>
  40. <p>La suite, je ne m'en souviens plus...
  41. </description>
  42. <xml_parse processor="JAXP"/>
  43. </document>
  44. <remarques>
  45. Mon document ne parse pas
  46. </remarques>
  47. <!-- il y a quelques erreurs -->
  48. fin du document
  49.  

Survolez les numéros pour afficher une explication sur les erreurs.

  1. <?xml version="1.0" encoding="1iso-8859-1" standalone="2yes"?>
  2. <?xml-stylesheet type="text/xsl" href="fg.xsl"?>
  3. <!-- à relire -->
  4. <?robots index="yes" follow="no"?>
  5. <document>
  6. <titre 3style="bold" Style="big">Mes mémoires</titre>
  7. <auteur>
  8. <nom>Gump</nom>
  9. <prénom>Forrest</prénom>
  10. 4</auteur>
  11. <description xmlns="http://www.w3.org/1999/xhtml"
  12. style="bold" Style="big" xml:space="preserve">
  13. <!-- à partir d'ici, on peut utiliser
  14. des éléments HTML 5<!&#45;&#45; et d'autres aussi &#45;&#45;>
  15. c'est pratique pour du contenu
  16. documentaire -->
  17. <p xml:space="default" 6align='center'>Ma maman disait
  18. toujours : &#xA; "<i>la vie c'est comme une
  19. 7boîte de 8<b>chocolat</b>, on ne sait jamais
  20. sur quoi on va tomber</i>".</p>
  21. <hr 9width=""/>
  22. <a xlink:href="bubbagump.avi"
  23. xmlns:xlink="http://www.w3.org/1999/xlink"
  24. href="bubbagump.avi"
  25. xlink:role="mon film">
  26. <object 10
  27. xlink:href="bubbagump.avi"/>
  28. </a>
  29. <script language="JavaScript">
  30. <![CDATA[
  31. function check() {
  32. for (int i=10; i>0; i++) {
  33. if ( a[b[i11]]>]]>5 ) break;
  34. }
  35. }
  36.  
  37. <!-- vérifier si la boucle doit scrire
  38. avec 12i&#45;&#45; et pas i++ -->
  39. </script>
  40. <p>La suite, je ne m'en souviens plus...13</p>
  41. </description>
  42. 14<xml_parse processor="JAXP"/>
  43. 15<remarques>
  44. Mon document ne parse pas
  45. </remarques>
  46. </document>
  47. <!-- il y a quelques erreurs -->
  48. 16

Fichier corrigé: tp/xml/forrest-ok.xml

Si le fichier corrigé ne se charge pas dans votre browser, ce n'est pas dû à une erreur syntaxique XML mais probablement dû au comportement de votre navigateur qui réagit sur l'instruction de traitement <?xsl-stylesheet?> et ne trouve pas la ressource référencée.

Essayez de mettre entre commentaire cette instruction de traitement pour voir comment votre navigateur va afficher le document.

Une fois le document corrigé, répondez aux questions suivantes :

  • Est-ce que ce document est bien formé (oui/non) ?
    Oui, puisque toutes les erreurs ont été corrigées.
  • Est-ce que ce document est valide (oui/non) ?
    On ne sait pas : il faudrait connaître le shéma pour pouvoir se prononcer.

Programmez un parseur pour valider l'instance avec une DTD. On utilisera JAXP (package javax.xml.parsers).

  1. import javax.xml.parsers.*;
  2.  
  3. public class MonParserValidantQuiValide {
  4.  
  5. public static void main( String[] args ) throws Exception {
  6. DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
  7. factory.setValidating( true );
  8. DocumentBuilder parser = factory.newDocumentBuilder();
  9. parser.parse( args[0] );
  10. }
  11. }

Pour lancer le programme :

  1. java -cp . MonParserValidantQuiValide forrest.xml

Ecrivez une DTD pour ce document et modifiez-le pour qu'elle soit référencée dans l'instance XML (<!DOCTYPE ...>).

Utilisez votre parseur validant pour vérifier que votre instance est conforme à la DTD.

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!ELEMENT a (object)>
  3. <!ATTLIST a
  4. href NMTOKEN #REQUIRED
  5. xlink:href NMTOKEN #REQUIRED
  6. xlink:role CDATA #REQUIRED
  7. xmlns:xlink CDATA #FIXED "http://www.w3.org/1999/xlink"
  8. >
  9. <!ELEMENT auteur (nom,prénom)>
  10. <!ELEMENT b (#PCDATA)>
  11. <!ELEMENT description (a|hr|p|script)*>
  12. <!ATTLIST description
  13. Style NMTOKEN #REQUIRED
  14. style NMTOKEN #REQUIRED
  15. xml:space NMTOKEN #REQUIRED
  16. xmlns CDATA #FIXED "http://www.w3.org/1999/xhtml"
  17. >
  18. <!ELEMENT document (titre,auteur,description,xml_parse,remarques)>
  19. <!ELEMENT hr EMPTY>
  20. <!ATTLIST hr width NMTOKEN #REQUIRED>
  21. <!ELEMENT i (#PCDATA|b)*>
  22. <!ELEMENT nom (#PCDATA)>
  23. <!ELEMENT object EMPTY>
  24. <!ATTLIST object xlink:href NMTOKEN #REQUIRED>
  25. <!ELEMENT p (#PCDATA|i)*>
  26. <!ATTLIST p
  27. align NMTOKEN #IMPLIED
  28. xml:space NMTOKEN #IMPLIED
  29. >
  30. <!ELEMENT prénom (#PCDATA)>
  31. <!ELEMENT remarques (#PCDATA)>
  32. <!ELEMENT script (#PCDATA)>
  33. <!ATTLIST script language NMTOKEN #REQUIRED>
  34. <!ELEMENT titre (#PCDATA)>
  35. <!ATTLIST titre
  36. Style NMTOKEN #REQUIRED
  37. style NMTOKEN #REQUIRED
  38. >
  39. <!ELEMENT xml_parse EMPTY>
  40. <!ATTLIST xml_parse processor NMTOKEN #REQUIRED>

Insérez la ligne 2 dans le fichier XML :

  1. <?xml version="1.0" encoding="iso-8859-1" standalone="yes"?>
  2. <!DOCTYPE document SYSTEM "forrest-ok.dtd">
  3. <?xml-stylesheet type="text/xsl" href="fg.xsl"?>
  4. <!-- à relire -->
  5. <?robots index="yes" follow="no"?>
  6. <document>
  7. ...

Structuration des données

Vous êtes l'informaticien d'un Zoo. On vous demande d'organiser les données du Zoo en XML.

Concevez une petite instance en XML qui permet de gérer les animaux du zoo (primates : gorilles, babouins...; fauves : lions, tigres...), leurs caractéristiques physiques (nom, sexe, taille, poids, date de naissance, etc) et éventuellement des avertissements (animaux dangereux, ne pas nourrir, ne pas entrer dans la cage, etc).

  1. <?xml version="1.0" encoding="ISO-8859-1" ?>
  2. <!DOCTYPE zoo SYSTEM "zoo.dtd" [
  3. <!ENTITY % notations SYSTEM "notations.ent">
  4. %notations;
  5. <!ENTITY flipper.jpg SYSTEM "flipper.jpg" NDATA jpg>
  6. <!ENTITY oum.jpg SYSTEM "oum.jpg" NDATA jpg>
  7. <!ENTITY ecco.jpg SYSTEM "ecco.jpg" NDATA jpg>
  8. ]>
  9. <!-- Un petit Zoo avec quelques animaux -->
  10. <zoo>
  11. <info>Ouvert tous les jours de 8h00 à 19h00</info>
  12. <info><img src="nourrir.gif" />Il est <b>interdit</b> de nourrir les animaux&#127;&#128;.</info>
  13. <aquarium>
  14. <mammifères-marins>
  15. <dauphins>
  16. <dauphin id="jhgtr13" photo="flipper.jpg" date-naissance="1997-4-1">
  17. <nom>Flipper</nom>
  18. <sexe>M</sexe>
  19. <taille unité="cm">215</taille>
  20. <poids unité="kg">105</poids>
  21. </dauphin>
  22. <dauphin id="lkjh45" photo="ecco.jpg" date-naissance="2003-10-23">
  23. <nom>Ecco</nom>
  24. <sexe>F</sexe>
  25. <taille unité="cm">202</taille>
  26. <poids unité="kg">98</poids>
  27. </dauphin>
  28. <dauphin id="kjlhy90" photo="oum.jpg" date-naissance="1996-12-25">
  29. <nom>Oum</nom>
  30. <sexe>F</sexe>
  31. <!-- c'est mon préféré -->
  32. <taille unité="cm">295</taille>
  33. <poids unité="kg" status="mesure approximative">190<!-- il faut refaire la pesée --></poids>
  34. </dauphin>
  35. </dauphins>
  36. </mammifères-marins>
  37. <poissons>
  38. <sélaciens>
  39. <danger>Il est <b>interdit</b> de nager avec les requins.</danger>
  40. <requin id="plojk09" espèce="marteau" date-naissance="1998-6-5">
  41. <nom>Oussama</nom>
  42. <sexe>M</sexe>
  43. <taille unité="cm">455</taille>
  44. <poids unité="kg">540</poids>
  45. <commentaire>A tendance a se jeter contre les murs
  46. <![CDATA[<<< marteau & cinglé !!! >>>]]>
  47. <!-- Il faudra bien le faire piquer un jour -->
  48. </commentaire>
  49. </requin>
  50. <requin id="vgyuh43" espèce="requin bleu" nom-savant="carcharias glaucus" date-naissance="2004-1-13">
  51. <nom>Saddam</nom>
  52. <sexe>M</sexe>
  53. <taille unité="cm">355</taille>
  54. <poids unité="kg" status="">425</poids>
  55. </requin>
  56. </sélaciens>
  57. </poissons>
  58. </aquarium>
  59. </zoo>

Ecrivez la DTD qui va avec. Que faut-il ajouter dans le document pour aider un parseur à valider le document ?

  1. <?xml version="1.0" encoding="ISO-8859-1" ?>
  2.  
  3. <!ENTITY nourrir.gif SYSTEM "nourrir.gif" NDATA gif>
  4.  
  5. <!ENTITY % block "p | info | danger | attention">
  6. <!ENTITY % inline "b | i | em | strong | stabilo | img">
  7. <!ENTITY % attractions "aquarium?, vivarium?, enclos?, volière?">
  8. <!ENTITY % animal "nom, sexe, taille, poids, commentaire?">
  9. <!ENTITY % animal-attr "
  10. id ID #REQUIRED
  11. espèce CDATA #IMPLIED
  12. nom-savant CDATA #IMPLIED
  13. photo ENTITY #IMPLIED
  14. date-naissance CDATA #REQUIRED
  15. ">
  16. <!ENTITY % u-attr "
  17. unité CDATA #REQUIRED
  18. status CDATA #IMPLIED
  19. ">
  20.  
  21. <!ELEMENT p (#PCDATA | %inline;)*>
  22. <!ELEMENT info (#PCDATA | %inline;)*>
  23. <!ELEMENT danger (#PCDATA | %inline;)*>
  24. <!ELEMENT attention (#PCDATA | %inline;)*>
  25.  
  26. <!ELEMENT b (#PCDATA | %inline;)*>
  27. <!ELEMENT i (#PCDATA | %inline;)*>
  28. <!ELEMENT em (#PCDATA | %inline;)*>
  29. <!ELEMENT strong (#PCDATA | %inline;)*>
  30. <!ELEMENT stabilo (#PCDATA | %inline;)*>
  31. <!ELEMENT img EMPTY>
  32. <!ATTLIST img src ENTITY #REQUIRED>
  33.  
  34. <!ELEMENT zoo ((%block;)*, %attractions;)>
  35.  
  36. <!ELEMENT aquarium (mammifères-marins?, poissons?)>
  37. <!ELEMENT mammifères-marins (dauphins?, baleines?, orques?)>
  38. <!ELEMENT poissons (sélaciens?)>
  39.  
  40. <!ELEMENT vivarium (serpents?, arachnéens?)>
  41. <!ELEMENT serpents (boas?)>
  42. <!ELEMENT arachnéens (mygales?)>
  43.  
  44. <!ELEMENT enclos (primates?, fauves?)>
  45. <!ELEMENT primates (gorilles?, orangs-outans?)>
  46. <!ELEMENT fauves (tigres?, lions?)>
  47.  
  48. <!ELEMENT volière (oiseaux-terrestres?, oiseaux-aquatiques?, rapaces?)>
  49. <!ELEMENT oiseaux-terrestres (autruches?)>
  50. <!ELEMENT oiseaux-aquatiques (pingouins?, manchots?)>
  51. <!ELEMENT rapaces (aigles?)*>
  52.  
  53. <!ELEMENT dauphins (%block; | dauphin)+>
  54. <!ELEMENT dauphin (%animal;)>
  55. <!ATTLIST dauphin %animal-attr;>
  56.  
  57. <!ELEMENT baleines (%block; | baleine)+>
  58. <!ELEMENT baleine (%animal;)>
  59. <!ATTLIST baleine %animal-attr;>
  60.  
  61. <!ELEMENT orques (%block; | orque)+>
  62. <!ELEMENT orque (%animal;)>
  63. <!ATTLIST orque %animal-attr;>
  64.  
  65. <!ELEMENT sélaciens (%block; | requin)+>
  66. <!ELEMENT requin (%animal;)>
  67. <!ATTLIST requin %animal-attr;>
  68.  
  69. <!ELEMENT boas (%block; | boa)+>
  70. <!ELEMENT boa (%animal;)>
  71. <!ATTLIST boa %animal-attr;>
  72.  
  73. <!ELEMENT mygales (%block; | mygale)+>
  74. <!ELEMENT mygale (%animal;)>
  75. <!ATTLIST mygale %animal-attr;>
  76.  
  77. <!ELEMENT gorilles (%block; | gorille)+>
  78. <!ELEMENT gorille (%animal;)>
  79. <!ATTLIST gorille %animal-attr;>
  80.  
  81. <!ELEMENT orangs-outans (%block; | orang-outan)+>
  82. <!ELEMENT orang-outan (%animal;)>
  83. <!ATTLIST orang-outan %animal-attr;>
  84.  
  85. <!ELEMENT tigres (%block; | tigre)+>
  86. <!ELEMENT tigre (%animal;)>
  87. <!ATTLIST tigre %animal-attr;>
  88.  
  89. <!ELEMENT lions (%block; | lion)+>
  90. <!ELEMENT lion (%animal;)>
  91. <!ATTLIST lion %animal-attr;>
  92.  
  93. <!ELEMENT autruches (%block; | autruche)+>
  94. <!ELEMENT autruche (%animal;)>
  95. <!ATTLIST autruche %animal-attr;>
  96.  
  97. <!ELEMENT pingoins (%block; | pingoin)+>
  98. <!ELEMENT pingoin (%animal;)>
  99. <!ATTLIST pingoin %animal-attr;>
  100.  
  101. <!ELEMENT manchots (%block; | manchot)+>
  102. <!ELEMENT manchot (%animal;)>
  103. <!ATTLIST manchot %animal-attr;>
  104.  
  105. <!ELEMENT aigles (%block; | aigle)+>
  106. <!ELEMENT aigle (%animal;)>
  107. <!ATTLIST aigle %animal-attr;>
  108.  
  109. <!ELEMENT nom (#PCDATA)>
  110. <!ELEMENT sexe (#PCDATA)>
  111. <!ELEMENT taille (#PCDATA)>
  112. <!ATTLIST taille %u-attr;>
  113.  
  114. <!ELEMENT poids (#PCDATA)>
  115. <!ATTLIST poids %u-attr;>
  116.  
  117. <!ELEMENT commentaire (#PCDATA | %block;)*>

La DTD est complétée avec cette petite entité :

  1. <?xml version="1.0" encoding="ISO-8859-1" ?>
  2. <!NOTATION jpg SYSTEM "images/jpeg">
  3. <!NOTATION gif SYSTEM "images/gif">

Pour aider un parseur à valider le document avec cette DTD, il faut ajouter la déclaration <!DOCTYPE zoo SYSTEM "zoo.dtd"> dans l'instance XML. Mais ce n'est pas suffisant pour que la validation soit réalisée automatiquement. En l'occurrence, les navigateurs lisent la DTD mais ne valident pas nécessairement. Il faut donc utiliser le parseur validant réalisé précédemment.

Programmez un parseur pour valider l'instance avec la DTD. On utilisera JAXP (package javax.xml.parsers).

tp/xml/MonParserValidantQuiValide.java.

Pour lancer le programme :

  1. java -cp . MonParserValidantQuiValide zoo.xml

Si vous n'avez jamais eu d'erreur, modifiez votre instance en introduisant volontairement des données en contradiction avec votre grammaire. Lancez à nouveau la validation. Qu'indique le parseur ?

Si on introduit des erreurs qui rendent le document non conforme à la DTD, (voir tp/xml/zoo-ko.xml) une exception est lancée :.

  1. bash-2.05b$ java -cp . MonParserValidantQuiValide zoo-ko.xml
  2. Warning: validation was turned on but an org.xml.sax.ErrorHandler was not set, which is probably not what is desired.
  3. Parser will use a default ErrorHandler to print the first 10 errors.
  4. Please call the 'setErrorHandler' method to fix this.
  5. Error: URI=file:/path/to/zoo-ko.xml Line=13: Element "zoo" does not allow "mammifères-marins" here.
  6. Error: URI=file:/path/to/zoo-ko.xml Line=36: Element "zoo" does not allow "poissons" here.

Modifiez votre programme pour qu'il affiche le nom de l'élément racine de votre document XML (package org.w3c.dom).

Il suffit de récupérer le résultat de l'analyse dans un org.w3c.dom.Document :

  1. import org.w3c.dom.*;
  2. ...
  3. Document doc = parser.parse( args[0] );
  4. System.out.println( doc.getDocumentElement().getNodeName() );