Développement Web et représentation de données :
Technologie XML, DTD, XSD et XSL ;
applications à la bureautique et à la bioinformatique
Exercices corrigés, série 2 : vérification et validation XML
gilles.hunault "at" univ-angers.fr
Table des matières cliquable
1. Ecriture de grammaires élémentaires
2. Grammaires moins élémentaires
3. Lecture de grammaires courantes de petite taille
4. Lecture de grammaires courantes de grande taille
5. Conversions entres grammaires DTD et XSD ; vérification de grammaires
6. Contraintes et facettes dans les schémas XSD
Il est possible d'afficher toutes les solutions via ?solutions=1.
1. Ecriture de grammaires élémentaires
Ecrire des grammaires DTD élémentaires associées aux fichiers serv00.xml, serv01.xml... serv05.xml de la série 1 d'exercices. On nommera serv00.dtd, serv01.dtd... serv05.dtd les fichiers-grammaires correspondants. Ecrire ensuite les grammaires élémentaires XSD associées.
Ecrire les grammaires DTD élémentaires associées aux fichiers pers01.xml, pers02.xml... pers04.xml de la série 1 d'exercices. On nommera pers01.dtd, pers02.dtd... pers04.dtd les fichiers-grammaires correspondants. Ecrire ensuite les grammaires XSD associées.
Peut-on imposer que les dates de naissance sont des entiers positifs supérieurs à 1870 ?
Idem avec les fichiers fasta01.xml à fasta05.xml puis pour agences03.xml et agences04.xml. Peut-on faire un include des grammaires services et personnes pour créer une grammaire agences ?
Remarque : après avoir écrit «à la main» les grammaires, on pourra essayer de trouver un générateur de tels fichiers au vu d'un fichier XML type.
Solution : afficher la solution
1.1 Grammaires pour les services
La première série de grammaires DTD est facile à construire puisqu'on a peu de niveaux dans la hiérarchie. Une fois qu'on a compris qu'un élément se déclare par <!ELEMENT ...> et que pour déclarer que Y est un attribut de X, il faut écrire <!ATTLIST X Y...>, le plus dur est fait pour les DTD. Comme l'énoncé ne précise aucune contrainte particulière, nous avons choisi la solution minimale : nous avons considéré que services ne pouvait pas être vide, que nomDeService et numService sont simplement des chaines de caractères obligatoires en tant qu'attribut, d'où le contenu (#PCDATA) pour les éléments et CDATA #REQUIRED pour les attributs.
Seule la grammaire serv03.dtd mérite un peu plus d'attention car la présence de retour-charriot dans serv03.xml empêche la définition en type EMPTY pour service.
serv00.xml serv01.xml serv02.xml serv03.xml serv04.xml serv05.xml
serv00.dtd serv01.dtd serv02.dtd serv03.dtd serv04.dtd serv05.dtd
serv00.xsd serv01.xsd serv02.xsd serv03.xsd serv04.xsd serv05.xsd
Pour les grammaires XSD, il y a le choix de définir directement les éléments dans la hiérarchie, comme pour serv00.xsd ou de définir des références aux éléments puis de définir les éléments, comme pour serv01.xsd. Ainsi, au lieu de serv05.xsd, nous aurions pu définir serv05autre.xsd. Après réflexion, il nous semble que l'approche par référence est plus modulaire. Ce sera donc celle que nous allons privilégier dans la suite des exercices.
1.2 Grammaires pour les personnes
pers01.xml pers02.xml pers03.xml pers04.xml
pers01.dtd pers02.dtd pers03.dtd pers04.dtd
pers01.xsd pers02.xsd pers03.xsd pers04.xsd
1.3 Grammaires pour les séquences Fasta
fasta01.xml fasta02.xml fasta03.xml fasta04.xml fasta05.xml
fasta01.dtd fasta02.dtd fasta03.dtd fasta04.dtd fasta05.dtd
fasta01.xsd fasta02.xsd fasta03.xsd fasta04.xsd fasta05.xsd
1.4 Grammaires pour les agences
agences03dtd.xml agences04dtd.xml agences05dtd.xml
agences03.dtd agences04.dtd agences05.dtd
agences03.xsd agences04.xsd agences05.xsd
Comme le montre la grammaire agences05.dtd, il est possible de réaliser des include pour une DTD à l'aide des entités paramétriques qu'on utilise avec %, à ne pas confondre avec une entité classique qui s'utilise avec &. XSD fournit des mécanismes plus complets avec xs:include et xs:import mais plus difficiles à mettre en oeuvre à cause des espaces des noms.
1.5 A propos de la génération automatique de grammaires
Une fois la syntaxe des fichiers DTD et XSD maitrisée, un outil comme trang permet d'automatiser la génération de grammaires à partir d'un ou plusieurs fichiers XML. Voici, avec la forme longue puis avec la forme courte, comment générer respectivement une grammaire DTD puis une grammaire XSD pour le fichier serv00.xml :
# génération de grammaire DTD à partir de fichier(s) XML via trang, forme longue java -jar $trangPath trang.jar -I xml -O dtd -i encoding=ISO8859-15 serv00.xml services.dtd # génération de grammaire XSD à partir de fichier(s) XML via trang, forme courte trang serv00.xml services.xsdVoici les grammaires produites :
<?xml encoding="UTF-8"?> <!ELEMENT services (service)+> <!ATTLIST services xmlns CDATA #FIXED ''> <!ELEMENT service (#PCDATA)> <!ATTLIST service xmlns CDATA #FIXED ''><?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"> <xs:element name="services"> <xs:complexType> <xs:sequence> <xs:element maxOccurs="unbounded" ref="service"/> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="service" type="xs:NCName"/> </xs:schema>Attention quand même à relire les grammaires générées car il peut y avoir des surprises !
2. Grammaires moins élémentaires
Ecrire les grammaires DTD et XSD associées au fichier dessin.xml de la série 1 d'exercices. On nommera dessin.dtd et dessin.xsd les fichiers-grammaires correspondants. On essaiera de paramétrer l'attribut couleur qui est commun.
Ecrire un fichier minimal ouimaisnon.xml qui est valide pour la grammaire g1.dtd mais non valide pour la grammaire g2.dtd. Fournir ensuite un fichier livre.xml valide pour g2.dtd.
Ecrire une grammaire pour le fichier films2 en DTD puis en XSD. Pourquoi ne peut-on pas parler de la grammaire DTD d'un fichier ?
Solution : afficher la solution
2.1 Solution pour dessin.xml
Là encore, pour dessin.xml, il y a peu d'éléments et d'attributs dans dessin.xml donc une grammaire DTD «vite fait» peut être dessin.dtd dont le contenu est :
<!-- dessin.dtd --> <!-- une grammaire élémentaire pour dessin.xml --> <!ELEMENT dessins (dessin+) > <!ELEMENT dessin (cercle|rectangle|triangle)* > <!ELEMENT cercle EMPTY > <!ELEMENT rectangle EMPTY> <!ELEMENT triangle EMPTY> <!ATTLIST dessins largeur CDATA "REQUIRED"> <!ATTLIST dessins hauteur CDATA "REQUIRED"> <!ATTLIST cercle xcentre CDATA "REQUIRED"> <!ATTLIST cercle ycentre CDATA "REQUIRED"> <!ATTLIST cercle rayon CDATA "REQUIRED"> <!ATTLIST cercle couleur CDATA "REQUIRED"> <!ATTLIST rectangle xcsg CDATA "REQUIRED"> <!ATTLIST rectangle ycsg CDATA "REQUIRED"> <!ATTLIST rectangle largeur CDATA "REQUIRED"> <!ATTLIST rectangle hauteur CDATA "REQUIRED"> <!ATTLIST rectangle couleur CDATA "REQUIRED"> <!ATTLIST triangle couleur CDATA "REQUIRED"> <!ATTLIST triangle xpoint1 CDATA "REQUIRED"> <!ATTLIST triangle ypoint1 CDATA "REQUIRED"> <!ATTLIST triangle xpoint2 CDATA "REQUIRED"> <!ATTLIST triangle ypoint2 CDATA "REQUIRED"> <!ATTLIST triangle xpoint3 CDATA "REQUIRED"> <!ATTLIST triangle ypoint3 CDATA "REQUIRED">Pour forcer les couleurs à ne prendre que les valeurs autorisées, on peut utiliser une liste de valeurs, soit :
<!-- dessin2.dtd --> <!-- une autre grammaire pour dessin.xml --> <!ELEMENT dessins (dessin+) > <!ELEMENT dessin (cercle|rectangle|triangle)* > <!ELEMENT cercle EMPTY > <!ELEMENT rectangle EMPTY> <!ELEMENT triangle EMPTY> <!ATTLIST dessins largeur CDATA "REQUIRED"> <!ATTLIST dessins hauteur CDATA "REQUIRED"> <!ATTLIST cercle couleur (bleu|jaune|rouge|vert) "bleu" > <!ATTLIST cercle xcentre CDATA "REQUIRED"> <!ATTLIST cercle ycentre CDATA "REQUIRED"> <!ATTLIST cercle rayon CDATA "REQUIRED"> <!ATTLIST rectangle couleur (bleu|jaune|rouge|vert) "bleu" > <!ATTLIST rectangle xcsg CDATA "REQUIRED"> <!ATTLIST rectangle ycsg CDATA "REQUIRED"> <!ATTLIST rectangle largeur CDATA "REQUIRED"> <!ATTLIST rectangle hauteur CDATA "REQUIRED"> <!ATTLIST triangle couleur (bleu|jaune|rouge|vert) "bleu" > <!ATTLIST triangle xpoint1 CDATA "REQUIRED"> <!ATTLIST triangle ypoint1 CDATA "REQUIRED"> <!ATTLIST triangle xpoint2 CDATA "REQUIRED"> <!ATTLIST triangle ypoint2 CDATA "REQUIRED"> <!ATTLIST triangle xpoint3 CDATA "REQUIRED"> <!ATTLIST triangle ypoint3 CDATA "REQUIRED">Pour éviter la duplication par copier/coller de cette liste des couleurs, le mieux est d'utiliser une entité paramétrique, qui fonctionne comme une entité HTML mais qui commence par le symbole % (pourcent) :
<!-- dessin3.dtd --> <!-- encore une autre grammaire pour dessin.xml --> <!ENTITY % couleur "(bleu|jaune|rouge|vert)" > <!ELEMENT dessins (dessin+) > <!ELEMENT dessin (cercle|rectangle|triangle)* > <!ELEMENT cercle EMPTY > <!ELEMENT rectangle EMPTY> <!ELEMENT triangle EMPTY> <!ATTLIST dessins largeur CDATA "REQUIRED"> <!ATTLIST dessins hauteur CDATA "REQUIRED"> <!ATTLIST cercle couleur %couleur; "bleu" > <!ATTLIST cercle xcentre CDATA "REQUIRED"> <!ATTLIST cercle ycentre CDATA "REQUIRED"> <!ATTLIST cercle rayon CDATA "REQUIRED"> <!ATTLIST rectangle couleur %couleur; "bleu" > <!ATTLIST rectangle xcsg CDATA "REQUIRED"> <!ATTLIST rectangle ycsg CDATA "REQUIRED"> <!ATTLIST rectangle largeur CDATA "REQUIRED"> <!ATTLIST rectangle hauteur CDATA "REQUIRED"> <!ATTLIST triangle couleur %couleur; "bleu" > <!ATTLIST triangle xpoint1 CDATA "REQUIRED"> <!ATTLIST triangle ypoint1 CDATA "REQUIRED"> <!ATTLIST triangle xpoint2 CDATA "REQUIRED"> <!ATTLIST triangle ypoint2 CDATA "REQUIRED"> <!ATTLIST triangle xpoint3 CDATA "REQUIRED"> <!ATTLIST triangle ypoint3 CDATA "REQUIRED">On peut aller encore plus loin et intégrer la couleur par défaut dans l'entité ou décider qu'il est plus modulaire de définir une autre entité pour la couleur par défaut
<!-- une entité pour la liste des couleurs et la couleur par défaut --> <!-- avec un exemple d'utilisation --> <!ENTITY % couleur "(bleu|jaune|rouge|vert) 'bleu' " > ... <!ATTLIST cercle couleur %couleur; > <!-- une entité pour la liste des couleurs et une autre entité pour la couleur par défaut --> <!-- avec un exemple d'utilisation --> <!ENTITY % couleur "(bleu|jaune|rouge|vert)" > <!ENTITY % couleur_def "'bleu'" > ... <!ATTLIST cercle couleur %couleur; %couleur_def; >Voici donc les 5 grammaires DTD possibes et leur traduction automatique en schéma XSD :
dessin1.dtd dessin2.dtd dessin3.dtd dessin4.dtd dessin5.dtd
dessin1.xsd dessin2.xsd dessin3.xsd dessin4.xsd dessin5.xsd
2.2 Solution pour les grammaires g1.dtd et g2.dtd
Il ne faut pas se laisser impressionner par la longueur de la grammaire g1.dtd car de nombreux de ses éléments sont facultatifs :
<!-- g1.dtd --> <!ELEMENT livre (preface?,introduction?,chapitres*,conclusion?,annexes?,references,infosPublications) > <!ELEMENT preface (#PCDATA) > <!ELEMENT introduction (#PCDATA) > <!ELEMENT chapitres (#PCDATA|chapitre)* > <!ELEMENT chapitre (section*) > <!ELEMENT section (#PCDATA) > <!ELEMENT conclusion (#PCDATA) > <!ELEMENT annexes (#PCDATA) > <!ELEMENT autre (#PCDATA) > <!ELEMENT suite (#PCDATA) > <!ELEMENT references ANY > <!ELEMENT infosPublications EMPTY >Donc si on se focalise sur les éléments obligatoires, on peut se limiter à un fichier ouimaisnon.xml comme celui-ci :
<?xml version="1.0" ?> <!-- ouimaisnon.xml --> <livre> <references> pomme <autre> poire </autre> scoubidou <suite /> fin </references> <infosPublications /> </livre>On notera au passage ce que permet le mot clé ANY pour l'élément references, qui, s'il permet de tester des documents en cours de rédaction, n'est pas très contraignant. De même en ce qui concerne (#PCDATA|chapitre)* pour l'élément chapitres. Pour vérifier que ce fichier est valide pour g1 mais non pour g2, le plus simple est d'utiliser xmlstarlet ou xmllint car on n'a pas besoin d'écrire explicitement <!DOCTYPE avant l'élément racine, ce que ne permet pas rxp :
$gh> rxp -s -v ouimaisnon.xml # n'affiche rien, donc ceci prouve que le fichier est bien formé RXP 1.5.0 Copyright Richard Tobin, LTG, HCRC, University of Edinburgh Input encoding UTF-8, output encoding UTF-8 $gh> rxp -s -V ouimaisnon.xml Warning: Document has no DTD, validating abandoned (detected at end of prolog of document file:///home/gh/public_html/Webrd/ouimaisnon.xml) $gh> xmlstarlet val -d g1.dtd ouimaisnon.xml ouimaisnon.xml - valid $gh> xmlstarlet val -d g2.dtd ouimaisnon.xml ouimaisnon.xml - invalid $gh> xmlstarlet val -e -d g2.dtd ouimaisnon.xml # il faut utiliser l'option -e pour voir le détail des erreurs ouimaisnon.xml:4.0: Element livre content does not follow the DTD, expecting (preface? , introduction? , partie+ , conclusion? , annexes? , references , infosPublications), got (references infosPublications ) ouimaisnon.xml:5.0: Element references was declared EMPTY this one has content ouimaisnon.xml:5.0: Element references does not carry attribute motclef ouimaisnon.xml:5.0: Element references does not carry attribute txtref ouimaisnon.xml:7.0: No declaration for element autre ouimaisnon.xml:11.0: No declaration for element suite ouimaisnon.xml:14.0: Element infosPublications does not carry attribute nref ouimaisnon.xml - invalid $gh> xmllint --noout --dtdvalid g1.dtd ouimaisnon.xml # n'affiche rien car valide pour g1 $gh> xmllint --noout --dtdvalid g2.dtd ouimaisnon.xml ouimaisnon.xml:4: element livre: validity error : Element livre content does not follow the DTD, expecting (preface? , introduction? , partie+ , conclusion? , annexes? , references , infosPublications), got (references infosPublications ) ouimaisnon.xml:5: element references: validity error : Element references was declared EMPTY this one has content ouimaisnon.xml:5: element references: validity error : Element references does not carry attribute motclef ouimaisnon.xml:5: element references: validity error : Element references does not carry attribute txtref ouimaisnon.xml:7: element autre: validity error : No declaration for element autre ouimaisnon.xml:11: element suite: validity error : No declaration for element suite ouimaisnon.xml:14: element infosPublications: validity error : Element infosPublications does not carry attribute nref Document ouimaisnon.xml does not validate against g2.dtd $gh> xmllint --noout --dtdvalid g2.dtd livre.xml # n'affiche rien car valide pour g2 $gh> xmlstarlet val -d g2.dtd livre.xml livre.xml - validPar contre, la grammaire g2.dtd est plus exigeante que la grammaire g1.dtd :
<!-- g2.dtd --> <!ELEMENT livre (preface?,introduction?,partie+,conclusion?,annexes?,references,infosPublications) > <!ELEMENT preface (#PCDATA) > <!ELEMENT introduction (#PCDATA) > <!ELEMENT partie (chapitre+) > <!ELEMENT chapitre (#PCDATA|section)* > <!ELEMENT section (#PCDATA) > <!ELEMENT conclusion (#PCDATA) > <!ELEMENT annexes (#PCDATA) > <!ELEMENT references EMPTY > <!ELEMENT infosPublications EMPTY > <!ATTLIST partie numpart ID #IMPLIED > <!ATTLIST chapitre numchap ID #REQUIRED > <!ATTLIST section numsec ID "REQUIRED" > <!ATTLIST references numref ID #IMPLIED > <!ATTLIST references txtref CDATA #REQUIRED > <!ATTLIST references motclef NMTOKEN #REQUIRED > <!ATTLIST infosPublications nref IDREF #REQUIRED > <!ATTLIST infosPublications date CDATA "?" >Donc un fichier livre.xml valide pour g2 est un peu plus technique et demande un peu plus de réflexion :
<?xml version="1.0" encoding="ISO-8859-15" ?> <!-- livre.xml --> <livre> <preface> Ceci est la préface. </preface> <introduction> Ceci est l'introduction. </introduction> <partie numpart="partie1"> <chapitre numchap="chap1.1"> Ceci est le chapitre 1 de la partie 1. </chapitre> <chapitre numchap="chap1.2"> Ceci est le chapitre 2 de la partie 1. </chapitre> </partie> <partie> <!-- partie 2 mais sans numpart explicite --> <chapitre numchap="chap2.1"> Ceci est le chapitre 1 de la partie 2. <section numsec="sec2.1.1"> ceci est etc. </section> <section numsec="sec2.1.2"> ceci est etc. </section> </chapitre> </partie> <partie numpart="partie3"> <chapitre numchap="chap3.1"> Ceci est le chapitre 1 de la partie 3. </chapitre> </partie> <conclusion> Ceci est la conclusion. </conclusion> <references numref="ref1" txtref="standard" motclef="demo" /> <infosPublications nref="ref1" /> </livre>Afin de vous entrainer à la lecture synoptique et comparative de DTD et XSD, voici donc les 2 grammaires DTD possibes et leur traduction automatique en schéma XSD :
2.3 Solution pour le fichier films2.xml
La grammaire pour films2.xml est un peu compliquée à écrire. D'abord parce qu'il y a une hiérarchie un peu moins évidente. Ensuite, parce que certains éléments ne sont pas renseignés, ce qui n'est pas très facile à détecter car les éléments absents ne le sont pas en début de fichier : certains films n'ont pas d'élément GENRE et certains films n'ont pas d'élément RESUME, certains artistes n'ont pas d'élément ANNEENAISS.
On pourrait éventuellement avoir une idée de la concomittance entre éléments et attributs à l'aide notre programme eltatt si on l'applique à films2.xml soit le résultat suivant.
On peut donc écrire la grammaire minimale suivante qui autorise à n'avoir aucun film ni aucun artiste :
<!-- films2.dtd --> <!ELEMENT FILMSETARTISTES (FILMS?,ARTISTES?) > <!ELEMENT FILMS (FILM*) > <!ELEMENT FILM (TITRE,GENRE?,PAYS,MES,ROLES,RESUME?) > <!ELEMENT TITRE (#PCDATA) > <!ELEMENT GENRE (#PCDATA) > <!ELEMENT PAYS (#PCDATA) > <!ELEMENT MES (#PCDATA) > <!ELEMENT ROLES (ROLE*) > <!ELEMENT ROLE (PRENOM,NOM,INTITULE) > <!ELEMENT PRENOM (#PCDATA) > <!ELEMENT NOM (#PCDATA) > <!ELEMENT INTITULE (#PCDATA) > <!ELEMENT RESUME (#PCDATA) > <!ATTLIST FILM Annee CDATA #REQUIRED > <!ATTLIST MES idref CDATA #REQUIRED > <!ELEMENT ARTISTES (ARTISTE*) > <!ELEMENT ARTISTE (ACTNOM,ACTPNOM,ANNEENAISS?) > <!ELEMENT ACTNOM (#PCDATA) > <!ELEMENT ACTPNOM (#PCDATA) > <!ELEMENT ANNEENAISS (#PCDATA) > <!ATTLIST ARTISTE id CDATA #REQUIRED >Il n'est pas possible de profiter directement des déclarations ID et IDREF des DTD car dans la norme XML un identifiant ou une référence à un identifiant ne peut pas être uniquement numérique (de façon plus précise, il ne doit pas commencer par un chiffre). Or, c'est souvent le cas lorsque l'attribut provient d'un champ autoincrémenté d'une base de données. Voici ce qui se passe si on essaie de valider :
@ghchu~/public_html/Webrd|(~gH) > xmlstarlet val -d films2.dtd films2dtd.xml films2dtd.xml - valid @ghchu~/public_html/Webrd|(~gH) > xmlstarlet val -d films3.dtd films2dtd.xml | head films2dtd.xml:7: element MES: validity error : Syntax of value for attribute idref of MES is not valid films2dtd.xml:19: element MES: validity error : Syntax of value for attribute idref of MES is not valid films2dtd.xml:29: element MES: validity error : Syntax of value for attribute idref of MES is not valid films2dtd.xml:41: element MES: validity error : Syntax of value for attribute idref of MES is not valid ... films2dtd.xml:591: element ARTISTE: validity error : Syntax of value for attribute id of ARTISTE is not valid films2dtd.xml:592: element ARTISTE: validity error : Syntax of value for attribute id of ARTISTE is not valid films2dtd.xml:593: element ARTISTE: validity error : Syntax of value for attribute id of ARTISTE is not valid films2dtd.xml:594: element ARTISTE: validity error : Syntax of value for attribute id of ARTISTE is not valid films2dtd.xml:595: element ARTISTE: validity error : Syntax of value for attribute id of ARTISTE is not valid films2dtd.xml:596: element ARTISTE: validity error : Syntax of value for attribute id of ARTISTE is not valid ... @ghchu~/public_html/Webrd|(~gH) > xmlstarlet val -s films2.xsd films2.xml films2.xml - valid @ghchu~/public_html/Webrd|(~gH) > xmlstarlet val -s films3.xsd films2.xml films2.xml - invalid @ghchu~/public_html/Webrd|(~gH) > xmlstarlet val -e -s films3.xsd films2.xml films2.xml:6: element MES: Schemas validity error : Element 'MES', attribute 'idref': '3' is not a valid value of the atomic type 'xs:IDREF'. films2.xml:18: element MES: Schemas validity error : Element 'MES', attribute 'idref': '4' is not a valid value of the atomic type 'xs:IDREF'. films2.xml:28: element MES: Schemas validity error : Element 'MES', attribute 'idref': '6' is not a valid value of the atomic type 'xs:IDREF'. films2.xml:40: element MES: Schemas validity error : Element 'MES', attribute 'idref': '9' is not a valid value of the atomic type 'xs:IDREF'. films2.xml:46: element MES: Schemas validity error : Element 'MES', attribute 'idref': '10' is not a valid value of the atomic type 'xs:IDREF'. films2.xml:58: element MES: Schemas validity error : Element 'MES', attribute 'idref': '13' is not a valid value of the atomic type 'xs:IDREF'. ... films2.xml:590: element ARTISTE: Schemas validity error : Element 'ARTISTE', attribute 'id': '6' is not a valid value of the atomic type 'xs:ID'. films2.xml:590: element ARTNOM: Schemas validity error : Element 'ARTNOM': This element is not expected. Expected is ( ACTNOM ). films2.xml:591: element ARTISTE: Schemas validity error : Element 'ARTISTE', attribute 'id': '3' is not a valid value of the atomic type 'xs:ID'. films2.xml:591: element ARTNOM: Schemas validity error : Element 'ARTNOM': This element is not expected. Expected is ( ACTNOM ). ...Si on modifie le fichier des films en ajoutant les 3 lettres art devant chaque identifiant et chaque référence d'identifiant, soit :
# version avec des id et des idrefs numériques <?xml version="1.0" encoding="ISO-8859-1"?> <!-- films3dtd.xml --> <!DOCTYPE FILMSETARTISTES SYSTEM "films3.dtd"> <FILMSETARTISTES> <FILMS> <FILM Annee='1958'> <TITRE>Vertigo</TITRE> <GENRE>Drame</GENRE><PAYS>USA</PAYS><MES idref="3"></MES> ... <ARTISTE id="119"><ACTNOM>Parillaud</ACTNOM><ACTPNOM>Anne</ACTPNOM><ANNEENAISS>1960</ANNEENAISS></ARTISTE> <ARTISTE id="120"><ACTNOM>Anglade</ACTNOM><ACTPNOM>Jean-Hughes</ACTPNOM><ANNEENAISS>1955</ANNEENAISS></ARTISTE> <ARTISTE id="121"><ACTNOM>Barr</ACTNOM><ACTPNOM>Jean-Marc</ACTPNOM><ANNEENAISS>1960</ANNEENAISS></ARTISTE> </ARTISTES> </FILMSETARTISTES> # version avec des id et des idrefs qui commencent par art # (seuls ces id et idrefs sont modélisables par ID et IDREF dans une DTD) <?xml version="1.0" encoding="ISO-8859-1"?> <!-- films3dtd.xml --> <!DOCTYPE FILMSETARTISTES SYSTEM "films3.dtd"> <FILMSETARTISTES> <FILMS> <FILM Annee='1958'> <TITRE>Vertigo</TITRE> <GENRE>Drame</GENRE><PAYS>USA</PAYS><MES idref="art3"></MES> ... <ARTISTE id="art119"><ACTNOM>Parillaud</ACTNOM><ACTPNOM>Anne</ACTPNOM><ANNEENAISS>1960</ANNEENAISS></ARTISTE> <ARTISTE id="art120"><ACTNOM>Anglade</ACTNOM><ACTPNOM>Jean-Hughes</ACTPNOM><ANNEENAISS>1955</ANNEENAISS></ARTISTE> <ARTISTE id="art121"><ACTNOM>Barr</ACTNOM><ACTPNOM>Jean-Marc</ACTPNOM><ANNEENAISS>1960</ANNEENAISS></ARTISTE> </ARTISTES> </FILMSETARTISTES>alors, on peut utiliser ID et IDREF comme suit :
<!-- films3.dtd --> <!ELEMENT FILMSETARTISTES (FILMS?,ARTISTES?) > <!ELEMENT FILMS (FILM*) > <!ELEMENT FILM (TITRE,GENRE?,PAYS,MES,ROLES,RESUME?) > <!ELEMENT TITRE (#PCDATA) > <!ELEMENT GENRE (#PCDATA) > <!ELEMENT PAYS (#PCDATA) > <!ELEMENT MES (#PCDATA) > <!ELEMENT ROLES (ROLE*) > <!ELEMENT ROLE (PRENOM,NOM,INTITULE) > <!ELEMENT PRENOM (#PCDATA) > <!ELEMENT NOM (#PCDATA) > <!ELEMENT INTITULE (#PCDATA) > <!ELEMENT RESUME (#PCDATA) > <!ATTLIST FILM Annee CDATA #REQUIRED > <!ATTLIST MES idref IDREF #REQUIRED > <!ELEMENT ARTISTES (ARTISTE*) > <!ELEMENT ARTISTE (ACTNOM,ACTPNOM,ANNEENAISS?) > <!ELEMENT ACTNOM (#PCDATA) > <!ELEMENT ACTPNOM (#PCDATA) > <!ELEMENT ANNEENAISS (#PCDATA) > <!ATTLIST ARTISTE id ID #REQUIRED >Voici par exemple les messages d'erreur si on oublie de fournir un identifiant, si on définit deux fois le même identifiant ou si on fait référence à un identifiant qui n'existe pas (nous avons mis art3333 au lieu de art3 comme référence pour le premier film) :
$gh> rxp -s -V films4dtd.xml Warning: Required attribute idref for element MES is not present in unnamed entity at line 20 char 52 of file:///home/gh/public_html/Webrd/films4dtd.xml Warning: Duplicate ID attribute value art6 in unnamed entity at line 593 char 19 of file:///home/gh/public_html/Webrd/films4dtd.xml Warning: The ID art3333 was referred to but never defined (detected at end of body of document file:///home/gh/public_html/Webrd/films4dtd.xml) $gh> xmllint --noout --dtdvalid films3.dtd --valid films4dtd.xml films4dtd.xml:20: element MES: validity error : Element MES does not carry attribute idref <GENRE>Science-fiction</GENRE><PAYS>USA</PAYS><MES></MES> ^ films4dtd.xml:593: element ARTISTE: validity error : ID art6 already defined <ARTISTE id="art6"><ACTNOM>Cameron</ACTNOM><ACTPNOM>James</ACTPNOM><ANNEENAISS>1 ^ films4dtd.xml:712: element MES: validity error : IDREF attribute idref references an unknown ID "art3333" ^ films4dtd.xml:20: element MES: validity error : Element MES does not carry attribute idref films4dtd.xml:593: element ARTISTE: validity error : ID art6 already defined films4dtd.xml:8: element MES: validity error : IDREF attribute idref references an unknown ID "art3333" Document films4dtd.xml does not validate against films3.dtd $gh> xmlstarlet val -d films3.dtd -e films4dtd.xml films4dtd.xml:593.12: ID art6 already defined <ARTISTE id="art6"><ACTNOM>Cameron</ACTNOM><ACTPNOM>James</ACTPNOM><ANNEENAISS>1 ^ films4dtd.xml:20.0: Element MES does not carry attribute idref films4dtd.xml:593.0: ID art6 already defined films4dtd.xml:8.0: IDREF attribute idref references an unknown ID "art3333" films4dtd.xml - invalidNous verrons dans la série 3 d'exercices, avec les transformations XSL, comment ajouter automatiquement les trois lettres art pour les attributs id et idfref, même si on peut le faire sous éditeur avec Edition/Remplacer tout ou avec un outil en ligne de commande comme sed ou perl en mode -i -e.
Il est clair qu'on ne peut pas parler de la grammaire d'un fichier XML, même si on précise DTD ou XSD car les exemples précécents montrent qu'on peut définir plusieurs grammaires pour lesquelles un même fichier XML est valide. C'est pourquoi on ne doit jamais dire qu'un fichier fichier XML est valide sans préciser la grammaire utilisée alors qu'il est tout-à-fait normal de dire qu'un fichier est bien formé sans rien préciser d'autre.
Voici les grammaires utilisées :
films2.dtd films3.dtd films2.xsd films3.xsd
3. Lecture de grammaires courantes de petite taille
Ecrire un fichier cv_minimal.xml minimal valide pour la grammaire cv.dtd.
Quels sont tous les éléments possibles qu'on peut utiliser dans un fichier XHTML 1.0 strict ? Quel élément peut avoir le plus d'attributs ? On commencera par donner leur nombre avant d'en fournir une liste alphabétique.
Comparer les éléments posibles en XHTML 1.0 strict et XHTML 1.0 Transitionnel. Comparer les éléments posibles en XHTML 1.0 strict et HTML 5..
Y a-t-il des grammaires pour les documents Microsoft Office et Open Office/Libre Office ? En DTD ou XSD ? Et au NCBI, pour les formats de données bioinformatiques ? Et pour UNIPROT ? Et pour EMBL-EBI ?
Solution : afficher la solution
3.1 Un fichier CV minimal
A la lecture de cv_minimal.xml on pourra constater que si la structure imposée est respectée, le remplissage laisse à désirer. Mais au moins les éléments et attributs obligatoires sont présents, même s'ils ne sont pas renseignés. Avec une grammaire XSD on pourrait imposer d'avoir au moins 1 caractère par champ (!), ce qui éviterait les informations vides.
<?xml version="1.0" encoding="ISO-8859-1" ?> <!-- Fichier cv_minimal.xml --> <!DOCTYPE cv SYSTEM "Dtd/cv.dtd"> <cv> <titre></titre> <cvnom></cvnom> <etatcivil> <nom></nom> <prenom></prenom> <naissance></naissance> <situation></situation> </etatcivil> <formations> <formation date-iso="" date="" datefin="" intitule="" description="" /> </formations> <connaissances> </connaissances> <professionnel> <experience date-iso="" date="" datefin="" client="" entreprise="" fonction=""> <missions> <mission></mission> </missions> <environnement> <technique type="0" nom="" description="" /> </environnement> </experience> </professionnel> </cv>3.2 Eléments et attributs en XHTML 1.0 Strict
Il faut bien sûr disposer de la DTD du langage pour réaliser cette partie d'exercice. Heureusement, le W3C nous la met à disposition à l'adresse http://www.w3.org/TR/xhtml1/dtds.html et une copie locale est Dtd/xhtml1-strict.dtd. Pour compter et trier les éléments, les commandes Unix nommées grep, wc et sort sont tout-à fait indiquées
$gh> grep "ELEMENT" Dtd/xhtml1-strict.dtd | wc -l 77 $gh> grep "ELEMENT" Dtd/xhtml1-strict.dtd | sort <!ELEMENT a %a.content;> <!ELEMENT abbr %Inline;> <!-- abbreviation --> <!ELEMENT acronym %Inline;> <!-- acronym --> <!ELEMENT address %Inline;> <!ELEMENT area EMPTY> <!ELEMENT base EMPTY> <!ELEMENT bdo %Inline;> <!-- I18N BiDi over-ride --> <!ELEMENT big %Inline;> <!-- bigger font --> <!ELEMENT b %Inline;> <!-- bold font --> <!ELEMENT blockquote %Block;> <!ELEMENT body %Block;> <!ELEMENT br EMPTY> <!-- forced line break --> <!ELEMENT button %button.content;> <!-- push button --> <!ELEMENT caption %Inline;> <!ELEMENT cite %Inline;> <!-- citation --> <!ELEMENT code %Inline;> <!-- program code --> <!ELEMENT col EMPTY> <!ELEMENT colgroup (col)*> <!ELEMENT dd %Flow;> <!ELEMENT del %Flow;> <!ELEMENT dfn %Inline;> <!-- definitional --> <!ELEMENT div %Flow;> <!-- generic language/style container --> <!ELEMENT dl (dt|dd)+> <!ELEMENT dt %Inline;> <!ELEMENT em %Inline;> <!-- emphasis --> <!ELEMENT fieldset (#PCDATA | legend | %block; | form | %inline; | %misc;)*> <!ELEMENT form %form.content;> <!-- forms shouldn't be nested --> <!ELEMENT h1 %Inline;> <!ELEMENT h2 %Inline;> <!ELEMENT h3 %Inline;> <!ELEMENT h4 %Inline;> <!ELEMENT h5 %Inline;> <!ELEMENT h6 %Inline;> <!ELEMENT head (%head.misc;, <!ELEMENT hr EMPTY> <!ELEMENT html (head, body)> <!ELEMENT i %Inline;> <!-- italic font --> <!ELEMENT img EMPTY> <!ELEMENT input EMPTY> <!-- form control --> <!ELEMENT ins %Flow;> <!ELEMENT kbd %Inline;> <!-- something user would type --> <!ELEMENT label %Inline;> <!ELEMENT legend %Inline;> <!-- fieldset label --> <!ELEMENT li %Flow;> <!ELEMENT link EMPTY> <!ELEMENT map ((%block; | form | %misc;)+ | area+)> <!ELEMENT meta EMPTY> <!ELEMENT noscript %Block;> <!ELEMENT object (#PCDATA | param | %block; | form | %inline; | %misc;)*> <!ELEMENT ol (li)+> <!ELEMENT optgroup (option)+> <!-- option group --> <!ELEMENT option (#PCDATA)> <!-- selectable choice --> <!ELEMENT param EMPTY> <!ELEMENT p %Inline;> <!ELEMENT pre %pre.content;> <!ELEMENT q %Inline;> <!-- inlined quote --> <!ELEMENT samp %Inline;> <!-- sample --> <!ELEMENT script (#PCDATA)> <!ELEMENT select (optgroup|option)+> <!-- option selector --> <!ELEMENT small %Inline;> <!-- smaller font --> <!ELEMENT span %Inline;> <!-- generic language/style container --> <!ELEMENT strong %Inline;> <!-- strong emphasis --> <!ELEMENT style (#PCDATA)> <!ELEMENT sub %Inline;> <!-- subscript --> <!ELEMENT sup %Inline;> <!-- superscript --> <!ELEMENT table <!ELEMENT tbody (tr)+> <!ELEMENT td %Flow;> <!ELEMENT textarea (#PCDATA)> <!-- multi-line text field --> <!ELEMENT tfoot (tr)+> <!ELEMENT thead (tr)+> <!ELEMENT th %Flow;> <!ELEMENT title (#PCDATA)> <!ELEMENT tr (th|td)+> <!ELEMENT tt %Inline;> <!-- fixed pitch font --> <!ELEMENT ul (li)+> <!ELEMENT var %Inline;> <!-- variable -->Par contre pour bien présenter ces éléments et compter le nombre d'attributs par éléments, il vaut mieux écrire un programme comme notre analyseur de dtd.
3.3 Comparaison des éléments en XHTML 1.0 Strict, Transitionnel et HTML5
A l'aide des deux fichiers grammaires officielles issues de http://www.w3.org/TR/xhtml1/dtds.html dont strict.dtd et trans.dtd sont des copies locales, il est facile d'écrire un programme de comparaison des divers éléments. Voir par exemple notre comparateur de DTD.
Les principaux éléments absents de XHTML 1.0 Strict sont donc applet, center et font.
HTML5 n'est pas défini de façon rigoureuse aujourd'hui, la grammaire utilisée dans le comparateur est donc provisoire...
3.4 Grammaires pour les suite Office et les formats bioinformatiques
Un document pour Open Office est nommé opendocument. Il n'y a pas une grammaire mais plein de grammaires au format XSD, accessibles par exemple sur le site schemacentral. On pourra au passage regarder ce qu'est uno.
Un document pour Microsoft Office correspond aussi aujourd'hui à ce qu'on nomme OOXML. On peut trouver les grammaires associées, là encore sous forme de schémas XSD, sur le site officiel Microsoft (archive locale).
Le NCBI fournit une page et des outils pour XML, respectivement aux adresses ToolBox XML et ncbixml.txt. Une longue liste de DTD associées est disponible à l'adresse dtd mais le NCBI fournit aussi des schémas, sur le site, dans le sous-répertoire schema.
La recherche du mot XML dans la documentation d'Uniprot renvoie la page query xml qui montre qu'Uniprot est très actif au niveau XML. Ainsi la page xml_news recense les changements les plus récents. On remarquera que sur la page des téléchargements des bases de données figurent les schémas XSD...
Un example de DTD associée à une entrée Uniprot est consultable sur code.google.com.
L'EMBL-EBI n'est pas en reste avec sa page de documentation XML et son convertisseur XML.
4. Lecture de grammaires courantes de grande taille
Quels sont tous les éléments possibles qu'on peut utiliser dans un fichier SVG selon la norme SVG 1.1 du 16 aout 2011 ? Quel élément peut avoir le plus d'attribut ? On commencera par donner leur nombre avant d'en fournir une liste alphabétique. Reprendre ensuite avec les fichiers RDF.
Solution : afficher la solution
Avec grep et wc, rien de plus simple pour compter les éléments :
> grep "ELEMENT" svg11-flat-20110816_elts.txt | wc -l 80 > grep "ELEMENT" svg11-flat-20110816_elts.txt <!ELEMENT %SVG.altGlyphDef.qname; %SVG.altGlyphDef.content; > <!ELEMENT %SVG.altGlyphItem.qname; %SVG.altGlyphItem.content; > <!ELEMENT %SVG.altGlyph.qname; %SVG.altGlyph.content; > <!ELEMENT %SVG.animateColor.qname; %SVG.animateColor.content; > <!ELEMENT %SVG.animateMotion.qname; %SVG.animateMotion.content; > <!ELEMENT %SVG.animate.qname; %SVG.animate.content; > <!ELEMENT %SVG.animateTransform.qname; %SVG.animateTransform.content; > <!ELEMENT %SVG.a.qname; %SVG.a.content; > <!ELEMENT %SVG.circle.qname; %SVG.circle.content; > <!ELEMENT %SVG.clipPath.qname; %SVG.clipPath.content; > <!ELEMENT %SVG.color-profile.qname; %SVG.color-profile.content; > <!ELEMENT %SVG.cursor.qname; %SVG.cursor.content; > <!ELEMENT %SVG.defs.qname; %SVG.defs.content; > <!ELEMENT %SVG.desc.qname; %SVG.desc.content; > <!ELEMENT %SVG.ellipse.qname; %SVG.ellipse.content; > <!ELEMENT %SVG.feBlend.qname; %SVG.feBlend.content; > <!ELEMENT %SVG.feColorMatrix.qname; %SVG.feColorMatrix.content; > <!ELEMENT %SVG.feComponentTransfer.qname; %SVG.feComponentTransfer.content; > <!ELEMENT %SVG.feComposite.qname; %SVG.feComposite.content; > <!ELEMENT %SVG.feConvolveMatrix.qname; %SVG.feConvolveMatrix.content; > <!ELEMENT %SVG.feDiffuseLighting.qname; %SVG.feDiffuseLighting.content; > <!ELEMENT %SVG.feDisplacementMap.qname; %SVG.feDisplacementMap.content; > <!ELEMENT %SVG.feDistantLight.qname; %SVG.feDistantLight.content; > <!ELEMENT %SVG.feFlood.qname; %SVG.feFlood.content; > <!ELEMENT %SVG.feFuncA.qname; %SVG.feFuncA.content; > <!ELEMENT %SVG.feFuncB.qname; %SVG.feFuncB.content; > <!ELEMENT %SVG.feFuncG.qname; %SVG.feFuncG.content; > <!ELEMENT %SVG.feFuncR.qname; %SVG.feFuncR.content; > <!ELEMENT %SVG.feGaussianBlur.qname; %SVG.feGaussianBlur.content; > <!ELEMENT %SVG.feImage.qname; %SVG.feImage.content; > <!ELEMENT %SVG.feMergeNode.qname; %SVG.feMergeNode.content; > <!ELEMENT %SVG.feMerge.qname; %SVG.feMerge.content; > <!ELEMENT %SVG.feMorphology.qname; %SVG.feMorphology.content; > <!ELEMENT %SVG.feOffset.qname; %SVG.feOffset.content; > <!ELEMENT %SVG.fePointLight.qname; %SVG.fePointLight.content; > <!ELEMENT %SVG.feSpecularLighting.qname; %SVG.feSpecularLighting.content; > <!ELEMENT %SVG.feSpotLight.qname; %SVG.feSpotLight.content; > <!ELEMENT %SVG.feTile.qname; %SVG.feTile.content; > <!ELEMENT %SVG.feTurbulence.qname; %SVG.feTurbulence.content; > <!ELEMENT %SVG.filter.qname; %SVG.filter.content; > <!ELEMENT %SVG.font-face-format.qname; %SVG.font-face-format.content; > <!ELEMENT %SVG.font-face-name.qname; %SVG.font-face-name.content; > <!ELEMENT %SVG.font-face.qname; %SVG.font-face.content; > <!ELEMENT %SVG.font-face-src.qname; %SVG.font-face-src.content; > <!ELEMENT %SVG.font-face-uri.qname; %SVG.font-face-uri.content; > <!ELEMENT %SVG.font.qname; %SVG.font.content; > <!ELEMENT %SVG.foreignObject.qname; %SVG.foreignObject.content; > <!ELEMENT %SVG.glyph.qname; %SVG.glyph.content; > <!ELEMENT %SVG.glyphRef.qname; %SVG.glyphRef.content; > <!ELEMENT %SVG.g.qname; %SVG.g.content; > <!ELEMENT %SVG.hkern.qname; %SVG.hkern.content; > <!ELEMENT %SVG.image.qname; %SVG.image.content; > <!ELEMENT %SVG.linearGradient.qname; %SVG.linearGradient.content; > <!ELEMENT %SVG.line.qname; %SVG.line.content; > <!ELEMENT %SVG.marker.qname; %SVG.marker.content; > <!ELEMENT %SVG.mask.qname; %SVG.mask.content; > <!ELEMENT %SVG.metadata.qname; %SVG.metadata.content; > <!ELEMENT %SVG.missing-glyph.qname; %SVG.missing-glyph.content; > <!ELEMENT %SVG.mpath.qname; %SVG.mpath.content; > <!ELEMENT %SVG.path.qname; %SVG.path.content; > <!ELEMENT %SVG.pattern.qname; %SVG.pattern.content; > <!ELEMENT %SVG.polygon.qname; %SVG.polygon.content; > <!ELEMENT %SVG.polyline.qname; %SVG.polyline.content; > <!ELEMENT %SVG.radialGradient.qname; %SVG.radialGradient.content; > <!ELEMENT %SVG.rect.qname; %SVG.rect.content; > <!ELEMENT %SVG.script.qname; %SVG.script.content; > <!ELEMENT %SVG.set.qname; %SVG.set.content; > <!ELEMENT %SVG.stop.qname; %SVG.stop.content; > <!ELEMENT %SVG.style.qname; %SVG.style.content; > <!ELEMENT %SVG.svg.qname; %SVG.svg.content; > <!ELEMENT %SVG.switch.qname; %SVG.switch.content; > <!ELEMENT %SVG.symbol.qname; %SVG.symbol.content; > <!ELEMENT %SVG.textPath.qname; %SVG.textPath.content; > <!ELEMENT %SVG.text.qname; %SVG.text.content; > <!ELEMENT %SVG.title.qname; %SVG.title.content; > <!ELEMENT %SVG.tref.qname; %SVG.tref.content; > <!ELEMENT %SVG.tspan.qname; %SVG.tspan.content; > <!ELEMENT %SVG.use.qname; %SVG.use.content; > <!ELEMENT %SVG.view.qname; %SVG.view.content; > <!ELEMENT %SVG.vkern.qname; %SVG.vkern.content; >Pour les attributs et entités, avec notre analyseur de DTD les chose se compliquent. Voir analyse SVG DTD.
5. Conversions entres grammaires DTD et XSD ; vérification de grammaires
Peut-on facilement convertir une grammaire DTD en grammaire XSD ? Si oui quel convertisseur peut-on utiliser ? Si non, expliquez pourquoi.
Peut-on facilement convertir une grammaire XSD en grammaire DTD ? Si oui quel convertisseur peut-on utiliser ? Si non, expliquez pourquoi.
Solution : afficher la solution
La syntaxe DTD est tellement simple qu'il est facile de la convertir en syntaxe XSD, par exemple avec trang :
# génération de grammaire DTD à partir de fichier(s) XML via trang, forme longue java -jar $trangPath trang.jar -I xml -O dtd -i encoding=ISO8859-15 serv00.xml services.dtd # génération de grammaire XSD à partir de fichier(s) XML via trang, forme courte trang serv00.xml services.xsdDe la même façon, la syntaxe XSD est tellement complexe qu'il est facile de trouver quelque chose qui ne se convertit pas en syntaxe DTD, par exemple la cardinalité maxOccurs="15".
Remarque : trang s'installe tout simplement sous Ubuntu via sudo apt-get install trang.
6. Contraintes et facettes dans les schémas XSD
Ecrire une grammaire XSD qui oblige à décrire une séquence fasta avec un identifiant ID qui correspond à l'expression régulière ^[A-U]{1,3}\d{5}$ et une séquence SEQ d'acides aminés d'une longueur d'au moins 20 AA.
L'ancienne numérotation des plaques minéralogiques se composait de trois parties (chiffres,lettres,département). Ecrire une grammaire XSD correspondante et des exemples de fichiers "voitures" ou "cartes grises". Reprendre avec la nouvelle numérotation des plaques françaises.
Solution : afficher la solution
Exercice non corrigé (volontairement).
7. Autres grammaires dont Relax NG ; espaces de noms
Un collègue vient de me fournir une grammaire validateur.rnc pour des fichiers XML comme paradis.xml. Le seul problème est qu'il s'agit d'un schéma Relax NG comme il dit. Comment peut-on s'en servir ? Peut-on le convertir en DTD, en XSD ?
Solution : afficher la solution
Facile, y'a qu'à installer trang !
La transformation, une fois trang installé, est assurée par :
trang -I rnc -O xsd validateur.rnc validateur.xsdVoici le fichier rnc original :
# RelaxNg Schema compact syntax start = element instance { attribute nom{xsd:string}, attribute nbgroupes{xsd:unsignedInt}, attribute nbattributs{xsd:unsignedInt}, attribute nbentités{xsd:unsignedInt}, element données{ element groupes { element groupe{ attribute id{IdGroupe}, attribute nom{xsd:string} }* }, # correspond aux colonnes element attributs { element attribut{ attribute id{IdAttribut}, attribute nom{xsd:string} }* }, # correspond aux lignes element entités{ element entité{ attribute id{IdEntite}, attribute ref{RefGroupe}, attribute nom{xsd:string}, # correspond aux cellules # ici on peut ommettre la reference si vides on conserve #les élements valuationPositives et valuationNégatives si pas d'attributs pour plus de visibilité element valuationsPositives{ attribute refs{RefsAttributs}? }, element valuationsNégatives{ attribute refs{RefsAttributs}? } }* } }, # en complément element résultats{ element statistiques{ element redondance{ attribute pourcentage{pourcentage}, element entités{ attribute refs{RefsEntites} }* }, element impossibilités{ element entités{ attribute refs{RefsEntites} }* } }, element caractérisations{ element groupe{ attribute ref{RefGroupe}, #mise sous forme text "&" equiv. "et" "|" equiv. "ou" et "~" equiv. "non" #et on conserve les élements groupe pour plus de visibilité si pas de formule (element formule{xsd:string})* }* } }? } # Types simples IdGroupe = xsd:ID { pattern = 'g[1-9][0-9]*' } RefGroupe = xsd:IDREF { pattern = 'g[1-9][0-9]*' } RefsGroupes = xsd:IDREFS { pattern = 'g[1-9][0-9]*( g[1-9][0-9]*)*' } IdAttribut = xsd:ID { pattern = 'a[1-9][0-9]*' } RefsAttributs = xsd:IDREFS { pattern = 'a[1-9][0-9]*( a[1-9][0-9]*)*' } IdEntite= xsd:ID { pattern = 'g[1-9][0-9]*e[1-9][0-9]*' } RefsEntites = xsd:IDREFS { pattern = 'g[1-9][0-9]*e[1-9][0-9]*( g[1-9][0-9]*e[1-9][0-9]*)*' } pourcentage = xsd:unsignedInt { maxInclusive = '100' }et sa traduction en xsd par trang :
<?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"> <!-- RelaxNg Schema compact syntax --> <xs:element name="instance"> <xs:complexType> <xs:sequence> <xs:element ref="données"/> <xs:element minOccurs="0" ref="résultats"/> </xs:sequence> <xs:attribute name="nom" use="required" type="xs:string"/> <xs:attribute name="nbgroupes" use="required" type="xs:unsignedInt"/> <xs:attribute name="nbattributs" use="required" type="xs:unsignedInt"/> <xs:attribute name="nbentités" use="required" type="xs:unsignedInt"/> </xs:complexType> </xs:element> <xs:element name="données"> <xs:complexType> <xs:sequence> <xs:element ref="groupes"/> <xs:element ref="attributs"/> <xs:element name="entités"> <xs:complexType> <xs:sequence> <xs:element minOccurs="0" maxOccurs="unbounded" ref="entité"/> </xs:sequence> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="groupes"> <xs:complexType> <xs:sequence> <xs:element minOccurs="0" maxOccurs="unbounded" name="groupe"> <xs:complexType> <xs:attribute name="id" use="required" type="IdGroupe"/> <xs:attribute name="nom" use="required" type="xs:string"/> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="attributs"> <xs:complexType> <xs:sequence> <xs:element minOccurs="0" maxOccurs="unbounded" ref="attribut"/> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="attribut"> <xs:complexType> <xs:attribute name="id" use="required" type="IdAttribut"/> <xs:attribute name="nom" use="required" type="xs:string"/> </xs:complexType> </xs:element> <xs:element name="entité"> <xs:complexType> <xs:sequence> <xs:element ref="valuationsPositives"/> <xs:element ref="valuationsNégatives"/> </xs:sequence> <xs:attribute name="id" use="required" type="IdEntite"/> <xs:attribute name="ref" use="required" type="RefGroupe"/> <xs:attribute name="nom" use="required" type="xs:string"/> </xs:complexType> </xs:element> <xs:element name="valuationsPositives"> <xs:complexType> <xs:attribute name="refs" type="RefsAttributs"/> </xs:complexType> </xs:element> <xs:element name="valuationsNégatives"> <xs:complexType> <xs:attribute name="refs" type="RefsAttributs"/> </xs:complexType> </xs:element> <xs:element name="résultats"> <xs:complexType> <xs:sequence> <xs:element ref="statistiques"/> <xs:element ref="caractérisations"/> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="statistiques"> <xs:complexType> <xs:sequence> <xs:element ref="redondance"/> <xs:element ref="impossibilités"/> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="redondance"> <xs:complexType> <xs:sequence> <xs:element minOccurs="0" maxOccurs="unbounded" name="entités"> <xs:complexType> <xs:attribute name="refs" use="required" type="RefsEntites"/> </xs:complexType> </xs:element> </xs:sequence> <xs:attribute name="pourcentage" use="required" type="pourcentage"/> </xs:complexType> </xs:element> <xs:element name="impossibilités"> <xs:complexType> <xs:sequence> <xs:element minOccurs="0" maxOccurs="unbounded" name="entités"> <xs:complexType> <xs:attribute name="refs" use="required" type="RefsEntites"/> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="caractérisations"> <xs:complexType> <xs:sequence> <xs:element minOccurs="0" maxOccurs="unbounded" name="groupe"> <xs:complexType> <xs:sequence> <xs:element minOccurs="0" maxOccurs="unbounded" ref="formule"/> </xs:sequence> <xs:attribute name="ref" use="required" type="RefGroupe"/> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="formule" type="xs:string"/> <!-- Types simples --> <xs:simpleType name="IdGroupe"> <xs:restriction base="xs:ID"> <xs:pattern value="g[1-9][0-9]*"/> </xs:restriction> </xs:simpleType> <xs:simpleType name="RefGroupe"> <xs:restriction base="xs:IDREF"> <xs:pattern value="g[1-9][0-9]*"/> </xs:restriction> </xs:simpleType> <xs:simpleType name="RefsGroupes"> <xs:restriction base="xs:IDREFS"> <xs:pattern value="g[1-9][0-9]*( g[1-9][0-9]*)*"/> </xs:restriction> </xs:simpleType> <xs:simpleType name="IdAttribut"> <xs:restriction base="xs:ID"> <xs:pattern value="a[1-9][0-9]*"/> </xs:restriction> </xs:simpleType> <xs:simpleType name="RefsAttributs"> <xs:restriction base="xs:IDREFS"> <xs:pattern value="a[1-9][0-9]*( a[1-9][0-9]*)*"/> </xs:restriction> </xs:simpleType> <xs:simpleType name="IdEntite"> <xs:restriction base="xs:ID"> <xs:pattern value="g[1-9][0-9]*e[1-9][0-9]*"/> </xs:restriction> </xs:simpleType> <xs:simpleType name="RefsEntites"> <xs:restriction base="xs:IDREFS"> <xs:pattern value="g[1-9][0-9]*e[1-9][0-9]*( g[1-9][0-9]*e[1-9][0-9]*)*"/> </xs:restriction> </xs:simpleType> <xs:simpleType name="pourcentage"> <xs:restriction base="xs:unsignedInt"> <xs:maxInclusive value="100"/> </xs:restriction> </xs:simpleType> </xs:schema>
8. Questions diverses
Comment fait-on pour tester si un fichier DTD est valide ? Et un fichier XSD ? On pourra utiliser bad.dtd et bad.xsd avec respectivement bad_dtd.xml et bad_xsd.xml.
Quelles sont les différences entre XSD 1.0 et XSD 1.1 ?
Faut-il toujours écrire <!DOCTYPE... pour tester si un fichier est valide par rapport à un fichier DTD donné ?
Quelle est la différence entre SVG et Tiny SVG ? Quelles sont leurs grammaires ?
Solution : afficher la solution
Exercice volontairement non corrigé.
Archive des données, programmes et scripts.
Code-source php de cette page ; code javascript utilisé. Retour à la page principale du cours.
Retour à la page principale de (gH)