Valid XHTML     Valid CSS2    

XML en M1 (2018), université d'Angers

    gilles.hunault@univ-angers.fr

 

T.P. numéro 1

 

Table des matières cliquable

  1. Rendre un document HTML valide pour la grammaire XHTML 1.0 Strict

  2. Passer de XHTML 1.0 Transitionnel à XHTML 1.0 Strict

  3. Créer un document XML qui respecte une grammaire DTD

  4. Créer un document XML qui respecte une grammaire XSD

  5. Créer des grammaires DTD et XSD

  6. Compter des éléments et des attributs

  7. Produire du XML avec MySQL

 

Il est possible d'afficher toutes les solutions via  ?solutions=1  et de les masquer via  ?solutions=0 .

 

1. Rendre un document HTML valide pour la grammaire XHTML 1.0 Strict

Ce n'est pas parce qu'un navigateur affiche un document qu'il est valide. Corriger le document HTML de l'archive m1xml_bad.zip pour qu'il soit valide pour la grammaire XHTML 1.0 Strict. On pourra utiliser des outils Web ou en ligne de commande.

Solution :  

Que ce soit à l'aide d'un outil Web comme le W3C validator, d'un outil intégré à Firefox comme HTML Validator ou d'un outil en ligne de commande comme rxp, xmllint ou xmlstarlet, on trouve les erreurs suivantes :

  • il manque la structure englobante html/head/body ;

  • il manque donc aussi l'élément title dans la partie head ;

  • le deuxième paragraphe qui commence en ligne 4 n'est pas fermé car il n'y a pas de </p> correspondant à son <p> ;

  • toujours en ligne 4 l'entité &nbsp est mal écrite, il manque un point-virgule en fin d'entité  ;

  • le lien pour Google est incorrect, il faut des guillemets autour de l'URL  ;

  • le lien pour Google est un élément inline et doit être inclus dans un élément de type boite comme par exemple un élément p ou div.

La page m1xml_ok.html contient une version corrigée de la page et avec une indication explicite du jeu de caractères utilisé.

Remarque : une page Web peut comporter autre chose que du HTML ; ainsi les erreurs CSS et JavaScript ne sont pas détectables via ces outils.

 

2. Passer de XHTML 1.0 Transitionnel à XHTML 1.0 Strict

Quelles sont les principales différences entre les grammaires XHTML 1.0 Transitionnel et XHTML 1.0 Strict ?

Solution :  

Comme le montre notre comparateur de grammaires DTD, ce sont surtout les éléments font, iframe et center qui ne sont plus admis en XHTML 1.0 Strict. Ce qui signifie qu'il faut utiliser plus de CSS.

On pourra lire l'article trans-vs-strict pour plus de détails.

Passer de XHTML 1.0 Transitionnel à XHTML 1.0 Strict peut être parfois compliqué. Ainsi pour démarrer une liste avec l'année courante (ici 2017), le code <ol start="2017"... est incorrect car l'attribut start est interdit en XHTML strict. Soit on passe par du CSS (mais cela se généralise mal) soit on utilise du code Javascript pour réaliser un setAttribute("start","2017", ce qui rajoute des difficultés...

 

3. Créer un document XML qui respecte une grammaire DTD

Nous admettrons pour ce qui suit qu'une molécule est définie par une liste d'atomes avec le nom des atomes, leur notation et le nombre de ces atomes fournis en attributs. Par exemple la molécule d'eau H2O est définie par l'atome de nom hydrogène, de notation H en nombre 2 et par l'atome de nom oxygène, de notation O et en nombre 1 (qui peut donc être omis). Après avoir lu soigneusement le fichier suivant nommé molecule.dtd, écrire un fichier eau.xml valide pour cette grammaire DTD. On utilisera un outil en ligne de commande pour vérifier cette validité. On pourra ignorer les accents.

Fichier molecule.dtd :


     <!ELEMENT molecule (atome)+ >
     <!ELEMENT atome    EMPTY    >
     
     <!ATTLIST atome    nom      CDATA  #REQUIRED >
     <!ATTLIST atome    lettre   CDATA  #REQUIRED >
     <!ATTLIST atome    nombre   CDATA  "1"       >
     

Est-ce que cette grammaire DTD autorise les chaines vides pour les noms, lettres et nombres ?

Est-ce qu'il faut respecter l'ordre des attributs tel qu'il est défini dans la grammaire DTD ?

Solution :  

Voici un fichier eau.xml possible :


     <?xml version="1.0" ?>
     <molecule>
       <atome nom="Hydrogene" lettre="H" nombre="2" />
       <atome nom="Oxygene"   lettre="O" nombre="1" />
     </molecule>
     

On peut vérifier la validité de ce fichier pour la grammaire molecule.dtd via les commandes suivantes :


     xmllint --dtdvalid molecule.dtd --valid eaudtd.xml
     
     xmlstarlet val -d molecule.dtd eau.xml
     

Hélas, oui cette grammaire DTD autorise les chaines vides pour les noms, lettres et les nombres car CDATA, comme #PCDATA inclut la chaine vide. On pourra s'en rendre compte avec le fichier suivant eauvide.xml qui est valide pour cette grammaire. Attention : une chaine de caractères réduite à un espace est aussi valide, mais vraiment peut informative...

De la même façon, l'ordre des attributs est libre, à condition qu'un attribut n'apparaisse pas deux fois, comme le montre le fichier suivant, qui est valide pour la DTD considérée :

Fichier eaudtdatt.xml :


     <?xml version="1.0" ?>
     <!DOCTYPE molecule SYSTEM "molecule.dtd">
     <molecule>
       <atome lettre=""  nom=""  nombre="" />
       <atome nombre=""  nom=""  lettre="" />
     </molecule>
     

Voici le message d'erreur en cas de duplication d'attribut, comme c'est le cas pour le fichier eaudtdatt2.xml :


     <?xml version="1.0" ?>
     <!-- fichier  eaudtdatt2.xml -->
     <!DOCTYPE molecule SYSTEM "molecule.dtd">
     <molecule>
       <atome lettre=""  nom=""  nombre="" />
       <atome nombre=""  nom=""  lettre="" nombre = "" />
     </molecule>
     

     $gh> xmlstarlet val -e -d molecule.dtd eaudtdatt2.xml
     
     eaudtdatt2.xml:5.51: Attribute nombre redefined
     
     <atome nombre=""  nom=""  lettre="" nombre = "" />
                                                       ^
     eaudtdatt2.xml - invalid
     

 

4. Créer un document XML qui respecte une grammaire XSD

On décide maintenant d'utiliser la grammaire molecule.xsd suivante pour stocker les mêmes informations.

Fichier molecule.xsd :


     <?xml version="1.0" encoding="UTF-8"?>
     <xsd:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
     
       <xsd:element name="molecule">
         <xsd:complexType>
           <xsd:sequence>
             <xsd:element maxOccurs="unbounded" ref="atome"/>
           </xsd:sequence>
         </xsd:complexType>
       </xsd:element>
     
       <xsd:element name="atome">
         <xsd:complexType>
           <xsd:sequence>
             <xsd:element ref="nom"/>
             <xsd:element ref="nombre"/>
           </xsd:sequence>
         </xsd:complexType>
       </xsd:element>
     
       <xsd:element name="nom">
         <xsd:complexType>
            <xsd:simpleContent>
               <xsd:extension base="xsd:string">
                  <xsd:attribute name="lettre" use="required" type="xsd:string"/>
               </xsd:extension>
            </xsd:simpleContent>
         </xsd:complexType>
       </xsd:element>
     
       <xsd:element name="nombre" type="xsd:integer"/>
     
     </xsd:schema>
     

Ecrire un fichier eau2.xml valide pour cette grammaire XSD. On utilisera un outil en ligne de commande pour vérifier cette validité. Là encore, on pourra ignorer les accents.

Est-ce que cette grammaire XSD autorise les chaines vides pour les noms, lettres et nombres ?

Solution :  

Voici un fichier eau2.xml possible :


     <?xml version="1.0" ?>
     <molecule>
       <atome>
          <nom lettre="O">Oxygene</nom>
          <nombre>1</nombre>
       </atome>
       <atome>
          <nom lettre="H">Hydrogene</nom>
          <nombre>2</nombre>
       </atome>
     </molecule>
     

On peut vérifier la validité de ce fichier pour la grammaire molecule.xsd via les commandes suivantes :


     xmllint --noout --schema molecule.xsd eau2.xml
     
     xmlstarlet val -s molecule.xsd eau2.xml
     

Hélas, oui cette grammaire XSD autorise les chaines vides pour les noms, lettres, mais pas pour les nombres car xs:string inclut la chaine vide. On pourra s'en rendre compte avec le fichier suivant eau3.xml qui est valide pour cette grammaire. Attention : une chaine de caractères réduite à un espace est aussi valide, mais vraiment peut informative...

 

5. Créer des grammaires DTD et XSD

Disons qu'un trajet ferroviaire est représenté schématiquement mais obligatoirement par un numéro identifiant de trajet, un type de train, un lieu de départ et un lieu d'arrivée. Ces informations sont éventuellement complétées, lorsqu'elles sont disponibles, par deux informations ts (pour time stamp en anglais) qui fournissent respectivement la date et heure de départ et la date et heure d'arrivée.

Voici un exemple de fichier XML regroupant deux trajets, nommé trajets.xml.

Fichier trajets.xml :


     <trajets>
       <trajet id="tr02436">
            <train>TGV </train>
            <depart>Angers</depart>
            <arrive>Paris Montparnasse</arrive>
       </trajet>
       <trajet id="tr5897">
            <train>Micheline </train>
            <depart ts="2016-09-08 13:00">Troyes</depart>
            <arrive ts="2016-09-08 17:08">Dijon</arrive>
       </trajet>
     </trajets>
     

Donner pour ce fichier trajets.xml une grammaire DTD minimale et raisonnable qui permet de décrire les trajets ferroviaires puis une grammaire XSD équivalente.

Solution :  

On lira attentivement les fichiers ci-dessous.

Grammaire trajets.dtd :


     <!ELEMENT trajets (trajet)+                 >
     <!ELEMENT trajet  (train,depart,arrive)     >
     <!ELEMENT train   (#PCDATA)                 >
     <!ELEMENT depart  (#PCDATA)                 >
     <!ELEMENT arrive  (#PCDATA)                 >
     
     <!ATTLIST trajet  xmlns CDATA #FIXED '' id NMTOKEN #REQUIRED  >
     <!ATTLIST depart  xmlns CDATA #FIXED '' ts CDATA #IMPLIED     >
     <!ATTLIST arrive  xmlns CDATA #FIXED '' ts CDATA #IMPLIED     >
     

Grammaire trajets.xsd :


     <?xml version="1.0" encoding="UTF-8"?>
     <xsd:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
     
       <xsd:element name="trajets">
         <xsd:complexType>
           <xsd:sequence>
             <xsd:element maxOccurs="unbounded" ref="trajet"/>
           </xsd:sequence>
         </xsd:complexType>
       </xsd:element>
     
       <xsd:element name="trajet">
         <xsd:complexType>
           <xsd:sequence>
             <xsd:element ref="train"/>
             <xsd:element ref="depart"/>
             <xsd:element ref="arrive"/>
           </xsd:sequence>
           <xsd:attribute name="id" use="required" type="xsd:NCName"/>
         </xsd:complexType>
       </xsd:element>
     
       <xsd:element name="train" type="xsd:NCName"/>
     
       <xsd:element name="depart">
         <xsd:complexType>
           <xsd:simpleContent>
             <xsd:extension base="xsd:NCName">
               <xsd:attribute name="ts"/>
             </xsd:extension>
           </xsd:simpleContent>
         </xsd:complexType>
       </xsd:element>
     
       <xsd:element name="arrive">
         <xsd:complexType mixed="true">
           <xsd:attribute name="ts"/>
         </xsd:complexType>
       </xsd:element>
     
     </xsd:schema>
     

Il existe des outils pour créer automatiquement des grammaires à partir d'exemples, comme par exemple trang.

 

6. Compter des éléments et des attributs

Compter le nombre de lignes puis lister tous les éléments XML distincts utilisés dans le logo du renard ci-dessous, puis compter tous les éléments avec leurs attributs.

                              non su

Solution :  

Il y a en fait assez peu d'éléments utilisés pour le renard. Ainsi la commande xmlstarlet el -u firefox.svg renvoie une liste de 26 éléments distincts dans l'arbre, pour 348 éléments en tout. Si on retire les éléments égaux emboités comme g et g/g, il ne reste que 17 "vrais" éléments utilisés :


     # éléments issus de xmlstarlet el -u firefox.svg             # éléments uniques
     
     0001 svg                                                     0001 clipPath
     0002 svg/desc                                                0002 defs
     0003 svg/g                                                   0003 desc
     0004 svg/g/filter                                            0004 ellipse
     0005 svg/g/filter/feGaussianBlur                             0005 feGaussianBlur
     0006 svg/g/filter/feMerge                                    0006 feMerge
     0007 svg/g/filter/feMerge/feMergeNode                        0007 feMergeNode
     0008 svg/g/filter/feOffset                                   0008 feOffset
     0009 svg/g/g                                                 0009 filter
     0010 svg/g/g/ellipse                                         0010 g
     0011 svg/g/g/g                                               0011 linearGradient
     0012 svg/g/g/g/clipPath                                      0012 path
     0013 svg/g/g/g/clipPath/use                                  0013 radialGradient
     0014 svg/g/g/g/defs                                          0014 stop
     0015 svg/g/g/g/defs/ellipse                                  0015 svg
     0016 svg/g/g/g/linearGradient                                0016 title
     0017 svg/g/g/g/linearGradient/stop                           0017 use
     0018 svg/g/g/g/path
     0019 svg/g/g/g/radialGradient
     0020 svg/g/g/g/radialGradient/stop
     0021 svg/g/g/linearGradient
     0022 svg/g/g/linearGradient/stop
     0023 svg/g/g/path
     0024 svg/g/g/radialGradient
     0025 svg/g/g/radialGradient/stop
     0026 svg/title
     
     

Pour connaitre les attributs utilisés et pour compter chacun des éléments, on pourrait programmer le comptage des balises d'ouverture et de fermeture, ce que fait notre programme eltattres.php dont l'interface de départ est ici. On pourra cliquer sur le lien elementsRenard pour le vérifier et lire les comptages. On peut aussi enchainer de commandes :


      wc -l firefox.svg                                #  428 lignes
     
      xmlstarlet el    firefox.svg | wc -l             #  348 éléments
      xmlstarlet el -u firefox.svg | wc -l             #   26 éléments
      xmlstarlet el -a firefox.svg | wc -l             # 1311 éléments
      xmlstarlet el -a firefox.svg | grep "@" | wc -l  #  963 attributs
     

 

 

7. Produire du XML avec MySQL

Comment produire des documents XML correspondant aux tables d'une base de données MySQL ?

Solution :  

Il y a une option --xml dans les commandes mysql et mysqldump. La démonstration en sera faite dans le cadre du TP.

 

 

Questions sans réponse affichée dans le navigateur (donc venez en TP !)

  • Que faut-il changer dans les fichiers XML et dans les grammaires DTD et XSD précédentes si on décide d'utiliser des accents, que ce soit avec un encodage latin1 ou UTF ?

  • Est-ce qu'un navigateur peut être validant c'est-à-dire refuser l'affichage d'un document XML s'il n'est pas valide pour la grammaire indiquée en début de document ?

  • Après avoir vérifié qu'un document DOCX ou ODT est une archive (lisible par exemple par zip), chercher comment on peut lister tous les espaces de noms associés. Où trouve-t-on les grammaires pour ces documents ?

 

Code-source php de cette page.

 

 

retour gH    Retour à la page principale de   (gH)