Schémas XML Travaux Pratiques

Inria

Apprenez à modéliser un document XML en réalisant un schéma.

Ecrivez un programme Java qui permette de valider un document XML avec son schéma.

Prérequis

  • Java

Cours

  • XML
  • DTD
  • Schémas
  • JAXB

Conception d'un schéma XML

Zoo

On dispose du document XML :

<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE zoo SYSTEM "zoo.dtd" [
    <!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&#127;&#128;.</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 % notations SYSTEM "notations.ent">
%notations;

<!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 remplacer la DTD par un schéma du W3C.

Convertissez (à la main, sans aide d'outil qui le fasse automatiquement) la DTD en schéma du W3C. Remplassez les notations (attributs de type ENTITY dans la DTD) par le type xs:anyURI et ajoutez des types forts là où c'est possible (sexe, unités, valeurs numériques, dates, etc).

Associez le schéma au document et écrivez un programme Java qui permette de le valider (voir javax.xml.validation).

  • Que constatez-vous comme erreur ?
    Les dates dans le document XML n'ont pas un format standard.
  • Corrigez les données du document XML et revalidez
    Il suffit de mettre les dates au format AAAA-MM-JJ (remplacer "1997-4-1" par "1997-04-01")
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
    <xs:element name="block" abstract="true">
        <xs:complexType mixed="true">
            <xs:sequence>
                <xs:element minOccurs="0" maxOccurs="unbounded" ref="inline"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:element name="inline" abstract="true"/>
    <xs:group name="attractions">
        <xs:sequence>
            <xs:element minOccurs="0" ref="aquarium"/>
            <xs:element minOccurs="0" ref="vivarium"/>
            <xs:element minOccurs="0" ref="enclos"/>
            <xs:element minOccurs="0" ref="volière"/>
        </xs:sequence>
    </xs:group>
    <xs:complexType name="animal">
        <xs:sequence>
            <xs:element ref="nom"/>
            <xs:element ref="sexe"/>
            <xs:element ref="taille"/>
            <xs:element ref="poids"/>
            <xs:element minOccurs="0" ref="commentaire"/>
        </xs:sequence>
        <xs:attributeGroup ref="animal-attr"/>
    </xs:complexType>
    <xs:attributeGroup name="animal-attr">
        <xs:attribute name="id" use="required" type="xs:ID"/>
        <xs:attribute name="espèce"/>
        <xs:attribute name="nom-savant"/>
        <xs:attribute name="photo" type="xs:anyURI"/>
        <xs:attribute name="date-naissance" use="required" type="xs:date"/>
    </xs:attributeGroup>
    <xs:attributeGroup name="status-attr">
        <xs:attribute name="status"/>
    </xs:attributeGroup>
    <xs:element name="p" substitutionGroup="block"/>
    <xs:element name="info" substitutionGroup="block"/>
    <xs:element name="danger" substitutionGroup="block"/>
    <xs:element name="attention" substitutionGroup="block"/>
    <xs:element name="b" substitutionGroup="inline">
        <xs:complexType mixed="true">
            <xs:sequence>
                <xs:element minOccurs="0" maxOccurs="unbounded" ref="inline"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:element name="i" substitutionGroup="inline">
        <xs:complexType mixed="true">
            <xs:sequence>
                <xs:element minOccurs="0" maxOccurs="unbounded" ref="inline"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:element name="em" substitutionGroup="inline">
        <xs:complexType mixed="true">
            <xs:sequence>
                <xs:element minOccurs="0" maxOccurs="unbounded" ref="inline"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:element name="strong" substitutionGroup="inline">
        <xs:complexType mixed="true">
            <xs:sequence>
                <xs:element minOccurs="0" maxOccurs="unbounded" ref="inline"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:element name="stabilo" substitutionGroup="inline">
        <xs:complexType mixed="true">
            <xs:sequence>
                <xs:element minOccurs="0" maxOccurs="unbounded" ref="inline"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:element name="img" substitutionGroup="inline">
        <xs:complexType>
            <xs:attributeGroup ref="img-attlist"/>
        </xs:complexType>
    </xs:element>
    <xs:attributeGroup name="img-attlist">
        <xs:attribute name="src" use="required" type="xs:anyURI"/>
    </xs:attributeGroup>
    <xs:element name="zoo">
        <xs:complexType>
            <xs:sequence>
                <xs:element minOccurs="0" maxOccurs="unbounded" ref="block"/>
                <xs:group ref="attractions"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:element name="aquarium">
        <xs:complexType>
            <xs:sequence>
                <xs:element minOccurs="0" ref="mammifères-marins"/>
                <xs:element minOccurs="0" ref="poissons"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:element name="mammifères-marins">
        <xs:complexType>
            <xs:sequence>
                <xs:element minOccurs="0" ref="dauphins"/>
                <xs:element minOccurs="0" ref="baleines"/>
                <xs:element minOccurs="0" ref="orques"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:element name="poissons">
        <xs:complexType>
            <xs:sequence>
                <xs:element minOccurs="0" ref="sélaciens"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:element name="vivarium">
        <xs:complexType>
            <xs:sequence>
                <xs:element minOccurs="0" ref="serpents"/>
                <xs:element minOccurs="0" ref="arachnéens"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:element name="serpents">
        <xs:complexType>
            <xs:sequence>
                <xs:element minOccurs="0" ref="boas"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:element name="arachnéens">
        <xs:complexType>
            <xs:sequence>
                <xs:element minOccurs="0" ref="mygales"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:element name="enclos">
        <xs:complexType>
            <xs:sequence>
                <xs:element minOccurs="0" ref="primates"/>
                <xs:element minOccurs="0" ref="fauves"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:element name="primates">
        <xs:complexType>
            <xs:sequence>
                <xs:element minOccurs="0" ref="gorilles"/>
                <xs:element minOccurs="0" ref="orangs-outans"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:element name="fauves">
        <xs:complexType>
            <xs:sequence>
                <xs:element minOccurs="0" ref="tigres"/>
                <xs:element minOccurs="0" ref="lions"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:element name="volière">
        <xs:complexType>
            <xs:sequence>
                <xs:element minOccurs="0" ref="oiseaux-terrestres"/>
                <xs:element minOccurs="0" ref="oiseaux-aquatiques"/>
                <xs:element minOccurs="0" ref="rapaces"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:element name="oiseaux-terrestres">
        <xs:complexType>
            <xs:sequence>
                <xs:element minOccurs="0" ref="autruches"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:element name="oiseaux-aquatiques">
        <xs:complexType>
            <xs:sequence>
                <xs:element minOccurs="0" ref="manchots"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:element name="rapaces">
        <xs:complexType>
            <xs:sequence>
                <xs:element minOccurs="0" maxOccurs="unbounded" ref="aigles"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:element name="dauphins">
        <xs:complexType>
            <xs:choice maxOccurs="unbounded">
                <xs:element ref="block"/>
                <xs:element ref="dauphin"/>
            </xs:choice>
        </xs:complexType>
    </xs:element>
    <xs:element name="dauphin">
        <xs:complexType>
            <xs:complexContent>
                <xs:extension base="animal"/>
            </xs:complexContent>
        </xs:complexType>
    </xs:element>
    <xs:element name="baleines">
        <xs:complexType>
            <xs:choice maxOccurs="unbounded">
                <xs:element ref="block"/>
                <xs:element ref="baleine"/>
            </xs:choice>
        </xs:complexType>
    </xs:element>
    <xs:element name="baleine">
        <xs:complexType>
            <xs:complexContent>
                <xs:extension base="animal"/>
            </xs:complexContent>
        </xs:complexType>
    </xs:element>
    <xs:element name="orques">
        <xs:complexType>
            <xs:choice maxOccurs="unbounded">
                <xs:element ref="block"/>
                <xs:element ref="orque"/>
            </xs:choice>
        </xs:complexType>
    </xs:element>
    <xs:element name="orque">
        <xs:complexType>
            <xs:complexContent>
                <xs:extension base="animal"/>
            </xs:complexContent>
        </xs:complexType>
    </xs:element>
    <xs:element name="sélaciens">
        <xs:complexType>
            <xs:choice maxOccurs="unbounded">
                <xs:element ref="block"/>
                <xs:element ref="requin"/>
            </xs:choice>
        </xs:complexType>
    </xs:element>
    <xs:element name="requin">
        <xs:complexType>
            <xs:complexContent>
                <xs:extension base="animal"/>
            </xs:complexContent>
        </xs:complexType>
    </xs:element>
    <xs:element name="boas">
        <xs:complexType>
            <xs:choice maxOccurs="unbounded">
                <xs:element ref="block"/>
                <xs:element ref="boa"/>
            </xs:choice>
        </xs:complexType>
    </xs:element>
    <xs:element name="boa">
        <xs:complexType>
            <xs:complexContent>
                <xs:extension base="animal"/>
            </xs:complexContent>
        </xs:complexType>
    </xs:element>
    <xs:element name="mygales">
        <xs:complexType>
            <xs:choice maxOccurs="unbounded">
                <xs:element ref="block"/>
                <xs:element ref="mygale"/>
            </xs:choice>
        </xs:complexType>
    </xs:element>
    <xs:element name="mygale">
        <xs:complexType>
            <xs:complexContent>
                <xs:extension base="animal"/>
            </xs:complexContent>
        </xs:complexType>
    </xs:element>
    <xs:element name="gorilles">
        <xs:complexType>
            <xs:choice maxOccurs="unbounded">
                <xs:element ref="block"/>
                <xs:element ref="gorille"/>
            </xs:choice>
        </xs:complexType>
    </xs:element>
    <xs:element name="gorille">
        <xs:complexType>
            <xs:complexContent>
                <xs:extension base="animal"/>
            </xs:complexContent>
        </xs:complexType>
    </xs:element>
    <xs:element name="orangs-outans">
        <xs:complexType>
            <xs:choice maxOccurs="unbounded">
                <xs:element ref="block"/>
                <xs:element ref="orang-outan"/>
            </xs:choice>
        </xs:complexType>
    </xs:element>
    <xs:element name="orang-outan">
        <xs:complexType>
            <xs:complexContent>
                <xs:extension base="animal"/>
            </xs:complexContent>
        </xs:complexType>
    </xs:element>
    <xs:element name="tigres">
        <xs:complexType>
            <xs:choice maxOccurs="unbounded">
                <xs:element ref="block"/>
                <xs:element ref="tigre"/>
            </xs:choice>
        </xs:complexType>
    </xs:element>
    <xs:element name="tigre">
        <xs:complexType>
            <xs:complexContent>
                <xs:extension base="animal"/>
            </xs:complexContent>
        </xs:complexType>
    </xs:element>
    <xs:element name="lions">
        <xs:complexType>
            <xs:choice maxOccurs="unbounded">
                <xs:element ref="block"/>
                <xs:element ref="lion"/>
            </xs:choice>
        </xs:complexType>
    </xs:element>
    <xs:element name="lion">
        <xs:complexType>
            <xs:complexContent>
                <xs:extension base="animal"/>
            </xs:complexContent>
        </xs:complexType>
    </xs:element>
    <xs:element name="autruches">
        <xs:complexType>
            <xs:choice maxOccurs="unbounded">
                <xs:element ref="block"/>
                <xs:element ref="autruche"/>
            </xs:choice>
        </xs:complexType>
    </xs:element>
    <xs:element name="autruche">
        <xs:complexType>
            <xs:complexContent>
                <xs:extension base="animal"/>
            </xs:complexContent>
        </xs:complexType>
    </xs:element>
    <xs:element name="pingoins">
        <xs:complexType>
            <xs:choice maxOccurs="unbounded">
                <xs:element ref="block"/>
                <xs:element ref="pingoin"/>
            </xs:choice>
        </xs:complexType>
    </xs:element>
    <xs:element name="pingoin">
        <xs:complexType>
            <xs:complexContent>
                <xs:extension base="animal"/>
            </xs:complexContent>
        </xs:complexType>
    </xs:element>
    <xs:element name="manchots">
        <xs:complexType>
            <xs:choice maxOccurs="unbounded">
                <xs:element ref="block"/>
                <xs:element ref="manchot"/>
            </xs:choice>
        </xs:complexType>
    </xs:element>
    <xs:element name="manchot">
        <xs:complexType>
            <xs:complexContent>
                <xs:extension base="animal"/>
            </xs:complexContent>
        </xs:complexType>
    </xs:element>
    <xs:element name="aigles">
        <xs:complexType>
            <xs:choice maxOccurs="unbounded">
                <xs:element ref="block"/>
                <xs:element ref="aigle"/>
            </xs:choice>
        </xs:complexType>
    </xs:element>
    <xs:element name="aigle">
        <xs:complexType>
            <xs:complexContent>
                <xs:extension base="animal"/>
            </xs:complexContent>
        </xs:complexType>
    </xs:element>
    <xs:element name="nom" type="xs:string"/>
    <xs:element name="sexe" type="sexe"/>
    <xs:element name="taille">
        <xs:complexType>
            <xs:simpleContent>
                <xs:extension base="mesure">
                    <xs:attributeGroup ref="status-attr"/>
                    <xs:attribute name="unité" use="required">
                        <xs:simpleType>
                            <xs:restriction base="xs:string">
                                <xs:enumeration value="μm"/>
                                <xs:enumeration value="mm"/>
                                <xs:enumeration value="cm"/>
                                <xs:enumeration value="dm"/>
                                <xs:enumeration value="m"/>
                                <xs:enumeration value="dam"/>
                            </xs:restriction>
                        </xs:simpleType>
                    </xs:attribute>
                </xs:extension>
            </xs:simpleContent>
        </xs:complexType>
    </xs:element>
    <xs:element name="poids">
        <xs:complexType>
            <xs:simpleContent>
                <xs:extension base="mesure">
                    <xs:attributeGroup ref="status-attr"/>
                    <xs:attribute name="unité" use="required">
                        <xs:simpleType>
                            <xs:restriction base="xs:string">
                                <xs:enumeration value="μg"/>
                                <xs:enumeration value="mg"/>
                                <xs:enumeration value="cg"/>
                                <xs:enumeration value="dg"/>
                                <xs:enumeration value="g"/>
                                <xs:enumeration value="dag"/>
                                <xs:enumeration value="hg"/>
                                <xs:enumeration value="kg"/>
                                <xs:enumeration value="t"/>
                            </xs:restriction>
                        </xs:simpleType>
                    </xs:attribute>
                </xs:extension>
            </xs:simpleContent>
        </xs:complexType>
    </xs:element>
    <xs:element name="commentaire">
        <xs:complexType mixed="true">
            <xs:sequence>
                <xs:element minOccurs="0" maxOccurs="unbounded" ref="block"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:simpleType name="sexe">
        <xs:restriction base="xs:string">
            <xs:whiteSpace value="collapse"/>
            <xs:enumeration value="M"/>
            <xs:enumeration value="F"/>
            <xs:enumeration value="?"/>
        </xs:restriction>
    </xs:simpleType>
    <xs:simpleType name="mesure">
        <xs:restriction base="xs:float">
            <xs:minInclusive value="0"/>
        </xs:restriction>
    </xs:simpleType>
</xs:schema>

Schéma Relax NG

Refaites le même 1er exercice de modélisation de schéma avec Relax NG au lieu de W3C XML Schema.

<?xml version="1.0" encoding="UTF-8"?>
<grammar xmlns="http://relaxng.org/ns/structure/1.0" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
    <start>
        <ref name="zoo"/>
    </start>
    <define name="block">
        <choice>
            <ref name="p"/>
            <ref name="info"/>
            <ref name="danger"/>
            <ref name="attention"/>
        </choice>
    </define>
    <define name="inline">
        <choice>
            <ref name="b"/>
            <ref name="i"/>
            <ref name="em"/>
            <ref name="strong"/>
            <ref name="stabilo"/>
            <ref name="img"/>
        </choice>
    </define>
    <define name="attractions">
        <optional>
            <ref name="aquarium"/>
        </optional>
        <optional>
            <ref name="vivarium"/>
        </optional>
        <optional>
            <ref name="enclos"/>
        </optional>
        <optional>
            <ref name="volière"/>
        </optional>
    </define>
    <define name="animal">
        <interleave>
            <ref name="animal-attr"/>
        </interleave>
        <ref name="nom"/>
        <ref name="sexe"/>
        <ref name="taille"/>
        <ref name="poids"/>
        <optional>
            <ref name="commentaire"/>
        </optional>
    </define>
    <define name="animal-attr">
        <attribute name="id">
            <data type="ID"/>
        </attribute>
        <optional>
            <attribute name="espèce"/>
        </optional>
        <optional>
            <attribute name="nom-savant"/>
        </optional>
        <optional>
            <attribute name="photo">
                <data type="anyURI"/>
            </attribute>
        </optional>
        <attribute name="date-naissance">
            <data type="date"/>
        </attribute>
    </define>
    <define name="p">
        <element name="p">
            <zeroOrMore>
                <choice>
                    <text/>
                    <ref name="inline"/>
                </choice>
            </zeroOrMore>
        </element>
    </define>
    <define name="info">
        <element name="info">
            <zeroOrMore>
                <choice>
                    <text/>
                    <ref name="inline"/>
                </choice>
            </zeroOrMore>
        </element>
    </define>
    <define name="danger">
        <element name="danger">
            <zeroOrMore>
                <choice>
                    <text/>
                    <ref name="inline"/>
                </choice>
            </zeroOrMore>
        </element>
    </define>
    <define name="attention">
        <element name="attention">
            <zeroOrMore>
                <choice>
                    <text/>
                    <ref name="inline"/>
                </choice>
            </zeroOrMore>
        </element>
    </define>
    <define name="b">
        <element name="b">
            <zeroOrMore>
                <choice>
                    <text/>
                    <ref name="inline"/>
                </choice>
            </zeroOrMore>
        </element>
    </define>
    <define name="i">
        <element name="i">
            <zeroOrMore>
                <choice>
                    <text/>
                    <ref name="inline"/>
                </choice>
            </zeroOrMore>
        </element>
    </define>
    <define name="em">
        <element name="em">
            <zeroOrMore>
                <choice>
                    <text/>
                    <ref name="inline"/>
                </choice>
            </zeroOrMore>
        </element>
    </define>
    <define name="strong">
        <element name="strong">
            <zeroOrMore>
                <choice>
                    <text/>
                    <ref name="inline"/>
                </choice>
            </zeroOrMore>
        </element>
    </define>
    <define name="stabilo">
        <element name="stabilo">
            <zeroOrMore>
                <choice>
                    <text/>
                    <ref name="inline"/>
                </choice>
            </zeroOrMore>
        </element>
    </define>
    <define name="img">
        <element name="img">
            <attribute name="src">
                <data type="anyURI"/>
            </attribute>
            <empty/>
        </element>
    </define>
    <define name="zoo">
        <element name="zoo">
            <zeroOrMore>
                <ref name="block"/>
            </zeroOrMore>
            <ref name="attractions"/>
        </element>
    </define>
    <define name="aquarium">
        <element name="aquarium">
            <optional>
                <ref name="mammifères-marins"/>
            </optional>
            <optional>
                <ref name="poissons"/>
            </optional>
        </element>
    </define>
    <define name="mammifères-marins">
        <element name="mammifères-marins">
            <optional>
                <ref name="dauphins"/>
            </optional>
            <optional>
                <ref name="baleines"/>
            </optional>
            <optional>
                <ref name="orques"/>
            </optional>
        </element>
    </define>
    <define name="poissons">
        <element name="poissons">
            <optional>
                <ref name="sélaciens"/>
            </optional>
        </element>
    </define>
    <define name="vivarium">
        <element name="vivarium">
            <optional>
                <ref name="serpents"/>
            </optional>
            <optional>
                <ref name="arachnéens"/>
            </optional>
        </element>
    </define>
    <define name="serpents">
        <element name="serpents">
            <optional>
                <ref name="boas"/>
            </optional>
        </element>
    </define>
    <define name="arachnéens">
        <element name="arachnéens">
            <optional>
                <ref name="mygales"/>
            </optional>
        </element>
    </define>
    <define name="enclos">
        <element name="enclos">
            <optional>
                <ref name="primates"/>
            </optional>
            <optional>
                <ref name="fauves"/>
            </optional>
        </element>
    </define>
    <define name="primates">
        <element name="primates">
            <optional>
                <ref name="gorilles"/>
            </optional>
            <optional>
                <ref name="orangs-outans"/>
            </optional>
        </element>
    </define>
    <define name="fauves">
        <element name="fauves">
            <optional>
                <ref name="tigres"/>
            </optional>
            <optional>
                <ref name="lions"/>
            </optional>
        </element>
    </define>
    <define name="volière">
        <element name="volière">
            <optional>
                <ref name="oiseaux-terrestres"/>
            </optional>
            <optional>
                <ref name="oiseaux-aquatiques"/>
            </optional>
            <optional>
                <ref name="rapaces"/>
            </optional>
        </element>
    </define>
    <define name="oiseaux-terrestres">
        <element name="oiseaux-terrestres">
            <optional>
                <ref name="autruches"/>
            </optional>
        </element>
    </define>
    <define name="oiseaux-aquatiques">
        <element name="oiseaux-aquatiques">
            <optional>
                <ref name="pingoins"/>
            </optional>
            <optional>
                <ref name="manchots"/>
            </optional>
        </element>
    </define>
    <define name="rapaces">
        <element name="rapaces">
            <zeroOrMore>
                <optional>
                    <ref name="aigles"/>
                </optional>
            </zeroOrMore>
        </element>
    </define>
    <define name="dauphins">
        <element name="dauphins">
            <oneOrMore>
                <choice>
                    <ref name="block"/>
                    <ref name="dauphin"/>
                </choice>
            </oneOrMore>
        </element>
    </define>
    <define name="dauphin">
        <element name="dauphin">
            <ref name="animal"/>
        </element>
    </define>
    <define name="baleines">
        <element name="baleines">
            <oneOrMore>
                <choice>
                    <ref name="block"/>
                    <ref name="baleine"/>
                </choice>
            </oneOrMore>
        </element>
    </define>
    <define name="baleine">
        <element name="baleine">
            <ref name="animal"/>
        </element>
    </define>
    <define name="orques">
        <element name="orques">
            <oneOrMore>
                <choice>
                    <ref name="block"/>
                    <ref name="orque"/>
                </choice>
            </oneOrMore>
        </element>
    </define>
    <define name="orque">
        <element name="orque">
            <ref name="animal"/>
        </element>
    </define>
    <define name="sélaciens">
        <element name="sélaciens">
            <oneOrMore>
                <choice>
                    <ref name="block"/>
                    <ref name="requin"/>
                </choice>
            </oneOrMore>
        </element>
    </define>
    <define name="requin">
        <element name="requin">
            <ref name="animal"/>
        </element>
    </define>
    <define name="boas">
        <element name="boas">
            <oneOrMore>
                <choice>
                    <ref name="block"/>
                    <ref name="boa"/>
                </choice>
            </oneOrMore>
        </element>
    </define>
    <define name="boa">
        <element name="boa">
            <ref name="animal"/>
        </element>
    </define>
    <define name="mygales">
        <element name="mygales">
            <oneOrMore>
                <choice>
                    <ref name="block"/>
                    <ref name="mygale"/>
                </choice>
            </oneOrMore>
        </element>
    </define>
    <define name="mygale">
        <element name="mygale">
            <ref name="animal"/>
        </element>
    </define>
    <define name="gorilles">
        <element name="gorilles">
            <oneOrMore>
                <choice>
                    <ref name="block"/>
                    <ref name="gorille"/>
                </choice>
            </oneOrMore>
        </element>
    </define>
    <define name="gorille">
        <element name="gorille">
            <ref name="animal"/>
        </element>
    </define>
    <define name="orangs-outans">
        <element name="orangs-outans">
            <oneOrMore>
                <choice>
                    <ref name="block"/>
                    <ref name="orang-outan"/>
                </choice>
            </oneOrMore>
        </element>
    </define>
    <define name="orang-outan">
        <element name="orang-outan">
            <ref name="animal"/>
        </element>
    </define>
    <define name="tigres">
        <element name="tigres">
            <oneOrMore>
                <choice>
                    <ref name="block"/>
                    <ref name="tigre"/>
                </choice>
            </oneOrMore>
        </element>
    </define>
    <define name="tigre">
        <element name="tigre">
            <ref name="animal"/>
        </element>
    </define>
    <define name="lions">
        <element name="lions">
            <oneOrMore>
                <choice>
                    <ref name="block"/>
                    <ref name="lion"/>
                </choice>
            </oneOrMore>
        </element>
    </define>
    <define name="lion">
        <element name="lion">
            <ref name="animal"/>
        </element>
    </define>
    <define name="autruches">
        <element name="autruches">
            <oneOrMore>
                <choice>
                    <ref name="block"/>
                    <ref name="autruche"/>
                </choice>
            </oneOrMore>
        </element>
    </define>
    <define name="autruche">
        <element name="autruche">
            <ref name="animal"/>
        </element>
    </define>
    <define name="pingoins">
        <element name="pingoins">
            <oneOrMore>
                <choice>
                    <ref name="block"/>
                    <ref name="pingoin"/>
                </choice>
            </oneOrMore>
        </element>
    </define>
    <define name="pingoin">
        <element name="pingoin">
            <ref name="animal"/>
        </element>
    </define>
    <define name="manchots">
        <element name="manchots">
            <oneOrMore>
                <choice>
                    <ref name="block"/>
                    <ref name="manchot"/>
                </choice>
            </oneOrMore>
        </element>
    </define>
    <define name="manchot">
        <element name="manchot">
            <ref name="animal"/>
        </element>
    </define>
    <define name="aigles">
        <element name="aigles">
            <oneOrMore>
                <choice>
                    <ref name="block"/>
                    <ref name="aigle"/>
                </choice>
            </oneOrMore>
        </element>
    </define>
    <define name="aigle">
        <element name="aigle">
            <ref name="animal"/>
        </element>
    </define>
    <define name="nom">
        <element name="nom">
            <text/>
        </element>
    </define>
    <define name="sexe">
        <element name="sexe">
            <choice>
                <value>M</value>
                <value>F</value>
                <value>?</value>
            </choice>
        </element>
    </define>
    <define name="taille">
        <element name="taille">
            <attribute name="unité">
                <choice>
                    <value>μm</value>
                    <value>mm</value>
                    <value>cm</value>
                    <value>dm</value>
                    <value>m</value>
                    <value>dam</value>
                </choice>
            </attribute>
            <optional>
                <attribute name="status"/>
            </optional>
            <data type="float">
                <param name="minInclusive">0</param>
            </data>
        </element>
    </define>
    <define name="poids">
        <element name="poids">
            <attribute name="unité">
                <choice>
                    <value>μg</value>
                    <value>mg</value>
                    <value>cg</value>
                    <value>dg</value>
                    <value>g</value>
                    <value>dag</value>
                    <value>hg</value>
                    <value>kg</value>
                    <value>t</value>
                </choice>
            </attribute>
            <optional>
                <attribute name="status"/>
            </optional>
            <data type="float">
                <param name="minInclusive">0</param>
            </data>
        </element>
    </define>
    <define name="commentaire">
        <element name="commentaire">
            <ref name="commentaire-attlist"/>
            <zeroOrMore>
                <choice>
                    <text/>
                    <ref name="block"/>
                </choice>
            </zeroOrMore>
        </element>
    </define>
    <define name="commentaire-attlist" combine="interleave">
        <empty/>
    </define>
</grammar>

Ecrivez également le schéma sous forme "Relax NG compacte".

start = zoo
block = p | info | danger | attention
inline = b | i | em | strong | stabilo | img
attractions = aquarium?, vivarium?, enclos?, volière?
animal = (animal-attr), nom, sexe, taille, poids, commentaire?
animal-attr =
    attribute id { xsd:ID },
    attribute espèce { text }?,
    attribute nom-savant { text }?,
    attribute photo { xsd:anyURI }?,
    attribute date-naissance { xsd:date }
p = element p { (text | inline)* }
info = element info { (text | inline)* }
danger = element danger { (text | inline)* }
attention = element attention { (text | inline)* }
b = element b { (text | inline)* }
i = element i { (text | inline)* }
em = element em { (text | inline)* }
strong = element strong { (text | inline)* }
stabilo = element stabilo { (text | inline)* }
img =
    element img {
        attribute src { xsd:anyURI },
        empty
    }
zoo = element zoo { block*, attractions }
aquarium = element aquarium { mammifères-marins?, poissons? }
mammifères-marins =
    element mammifères-marins { dauphins?, baleines?, orques? }
poissons = element poissons { sélaciens? }
vivarium = element vivarium { serpents?, arachnéens? }
serpents = element serpents { boas? }
arachnéens = element arachnéens { mygales? }
enclos = element enclos { primates?, fauves? }
primates = element primates { gorilles?, orangs-outans? }
fauves = element fauves { tigres?, lions? }
volière =
    element volière {
        oiseaux-terrestres?, oiseaux-aquatiques?, rapaces?
    }
oiseaux-terrestres = element oiseaux-terrestres { autruches? }
oiseaux-aquatiques = element oiseaux-aquatiques { pingoins?, manchots? }
rapaces = element rapaces { aigles? }
dauphins = element dauphins { (block | dauphin)+ }
dauphin = element dauphin { animal }
baleines = element baleines { (block | baleine)+ }
baleine = element baleine { animal }
orques = element orques { (block | orque)+ }
orque = element orque { animal }
sélaciens = element sélaciens { (block | requin)+ }
requin = element requin { animal }
boas = element boas { (block | boa)+ }
boa = element boa { animal }
mygales = element mygales { (block | mygale)+ }
mygale = element mygale { animal }
gorilles = element gorilles { (block | gorille)+ }
gorille = element gorille { animal }
orangs-outans = element orangs-outans { (block | orang-outan)+ }
orang-outan = element orang-outan { animal }
tigres = element tigres { (block | tigre)+ }
tigre = element tigre { animal }
lions = element lions { (block | lion)+ }
lion = element lion { animal }
autruches = element autruches { (block | autruche)+ }
autruche = element autruche { animal }
pingoins = element pingoins { (block | pingoin)+ }
pingoin = element pingoin { animal }
manchots = element manchots { (block | manchot)+ }
manchot = element manchot { animal }
aigles = element aigles { (block | aigle)+ }
aigle = element aigle { animal }
nom = element nom { text }
sexe = element sexe { "M" | "F" | "?" }
taille =
    element taille {
        attribute unité { "μm" | "mm" | "cm" | "dm" | "m" | "dam" },
        attribute status { text }?,
        xsd:float { minInclusive = "0" }
    }
poids =
    element poids {
        attribute unité {
            "μg" | "mg" | "cg" | "dg" | "g" | "dag" | "hg" | "kg" | "t"
        },
        attribute status { text }?,
        xsd:float { minInclusive = "0" }
    }
commentaire =
    element commentaire { commentaire-attlist, (text | block)* }
commentaire-attlist &= empty

Utilisez Jing pour valider votre document avec un schéma Relax NG (formes XML et compacte). Lancez la validation en ligne de commande sans faire de programme Java.