- I. Validation d'un document XML.
- II. Les XML-Schémas (XMLS) : première étape
- III. Les XML-Schémas (XMLS) : deuxième étape
- IV. Schémas et instances de schémas
VerifSchema.java
/*
Emploi : java VerifSchema leSchema leFichier
*/
import org.xml.sax.SAXException;
import javax.xml.XMLConstants;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
import java.io.File;
import java.io.IOException;
public class VerifSchema {
public static void main(String[] args) {
String fichSchema = args[0];//"mySchema.xsd"
String fichXML = args[1]; //"myXMLDocument.xml"
try {
// Construire un validateur paramétré par le schéma
SchemaFactory factory =
SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
/* c'est à dire "http://www.w3.org/2001/XMLSchema".
une autre possibilité est XMLConstants.RELAXNG_NS_URI
qui signifie "http://relaxng.org/ns/structure/1.0".
*/
Schema schema;
try{
schema = factory.newSchema(new StreamSource(new
File(fichSchema)));
}catch(SAXException f){
System.out.println("Schéma incorrect : "+fichSchema + " : "+
f.getMessage());
throw new Exception("Erreur sur le schéma");
}
Validator validator = schema.newValidator();
// On valide un objet "Source" quelconque
Source src = new StreamSource (new File(fichXML));
validator.validate(src);
System.out.println(
"Le
fichier "+fichXML+" est valide par rapport au schema "+fichSchema);
} catch (SAXException e) {
System.out.println("Fichier XML invalide : "+e.getMessage());
} catch (IOException e) {
System.out.println("IO : "+e.getMessage());
} catch (Exception e) {
System.out.println("Erreur : "+e.getMessage());
} //try
}//main
}//VerifSchema
xsd:sequence
et xsd:choice
xsd:all
,
qui ne peut intervenir qu'à la racine du complexTypeelement
ou une annotation
(pas une sequence
ni un choice
) ; <xsd:complexType
name="ReviewInformation">
<xsd:all>
<xsd:element
name="review" type="xsd:string"/>
<xsd:element
name="author" type="xsd:string" minOccurs="0"/>
<xsd:element name="price" type="xsd:float"/>
</xsd:all>
<xsd:attribute name="reviewer" type="xsd:string"
/>
</xsd:complexType>
mixed
= "true"
complexType
ainsi
qualifié peut contenir du texte arbitraire autour des balises spécifiées<xsd:element name="letterBody">
<xsd:complexType mixed="true">
<xsd:sequence>
<xsd:element name="salutation">
<xsd:complexType
mixed="true">
<xsd:sequence>
<xsd:element
name="name" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="quantity"
type="xsd:positiveInteger"/>
<xsd:element name="productName"
type="xsd:string"/>
<xsd:element name="shipDate"
type="xsd:date" minOccurs="0"/>
<!-- etc. -->
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<letterBody>
<salutation>
Dear Mr.
<name>Robert
Smith</name>.
</salutation>
Your order of
<quantity>1</quantity>
<productName>Baby
Monitor</productName>
shipped from our warehouse on
<shipDate>1999-05-21</shipDate>.
....
</letterBody>
[ fichier Nom_note2.xml]
<?xml version="1.0" ?>
<liste>
<eleve>
<nom> Toto</nom> <note> 12
</note>
</eleve>
<eleve>
<nom> Tata</nom> <note> 13
</note>
</eleve>
<eleve>
<nom> Tutu</nom> <note> 17
</note>
</eleve>
<eleve>
<nom> Titi</nom> <note> 11
</note>
</eleve>
</liste>
En procédant de manière descendante, en définissant
systématiquement à chaque fois nos types "au vol",
suivant le procédé dit "de la poupée russe" (Russian Doll
Design) [fichier Nom_note2-1.xsd]
:
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<!-- Méthode de la poupée russe -->
<xsd:element name="liste">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="eleve"
minOccurs="0" maxOccurs="unbounded">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="nom" type="xsd:string"/>
<xsd:element name="note">
<xsd:simpleType>
<xsd:restriction base="xsd:integer">
<xsd:minInclusive
value="0"/>
<xsd:maxInclusive
value="20"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<!-- Méthode avec types -->
<xsd:element name="liste" type="listEleves"/>
<xsd:complexType name="listEleves">
<xsd:choice>
<xsd:element name="eleve" type="typEleve"
minOccurs="0"
maxOccurs="unbounded"/>
</xsd:choice>
</xsd:complexType>
<xsd:complexType name="typEleve">
<xsd:sequence>
<xsd:element name="nom" type="xsd:string"/>
<xsd:element name="note" type="noteSur20"/>
</xsd:sequence>
</xsd:complexType>
<xsd:simpleType name="noteSur20">
<xsd:restriction
base="xsd:integer">
<xsd:minInclusive value="0"/>
<xsd:maxInclusive value="20"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>
[ fichier Nom_note1.xml]
<?xml version="1.0" ?>
<liste>
<eleve nom="Toto"
note="12"/>
<eleve nom="Tata"
note="13"/>
<eleve nom="Tutu"
note="17"/>
<eleve nom="Tutu"
note="11"/>
</liste>
La méthode de la poupée russe donne un schéma très
semblable au précédent
[fichier Nom_note1-1.xsd]
:
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<!-- Méthode de la poupée russe -->
<xsd:element name="liste">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="eleve"
minOccurs="0" maxOccurs="unbounded">
<xsd:complexType>
<xsd:attribute name="nom"
type="xsd:string"/>
<xsd:attribute name="note">
<xsd:simpleType>
<xsd:restriction
base="xsd:integer">
<xsd:minInclusive value="0"/>
<xsd:maxInclusive value="20"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<xsd:complexType name="typEleve">
<xsd:attribute name="nom"
type="xsd:string"/>
<xsd:attribute name="note"
type="noteSur20"/>
</xsd:complexType>
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<!-- Partie commune -->
<xsd:element name="liste" type="listEleves"/>
<xsd:complexType name="listEleves">
<xsd:choice>
<xsd:element name="eleve" type="typEleve"
minOccurs="0"
maxOccurs="unbounded"/>
</xsd:choice>
</xsd:complexType>
<xsd:simpleType name="noteSur20">
<xsd:restriction
base="xsd:integer">
<xsd:minInclusive value="0"/>
<xsd:maxInclusive value="20"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<!-- Méthode avec réemploi -->
<xsd:include schemaLocation="Nom_note.xsd"/>
<xsd:complexType name="typEleve">
<xsd:sequence>
<xsd:element name="nom" type="xsd:string"/>
<xsd:element name="note" type="noteSur20"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<!-- Méthode avec réemploi -->
<xsd:include schemaLocation="Nom_note.xsd"/>
<xsd:complexType name="typEleve">
<xsd:attribute name="nom"
type="xsd:string"/>
<xsd:attribute name="note"
type="noteSur20"/>
</xsd:complexType>
</xsd:schema>
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<!-- Méthode avec refs -->
<xsd:element name="liste">
<xsd:complexType>
<xsd:choice>
<xsd:element ref="eleve"
minOccurs="0" maxOccurs="unbounded"/>
</xsd:choice>
</xsd:complexType>
</xsd:element>
<xsd:element name="eleve">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="nom"
type="xsd:string"/>
<xsd:element name="note"
type="noteSur20"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:simpleType name="noteSur20">
<xsd:restriction
base="xsd:integer">
<xsd:minInclusive value="0"/>
<xsd:maxInclusive value="20"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>
<xsd:element name="Transmission" type="typTrans"/>
<xsd:complexType name="typtrans" >
<xsd:sequence>
<xsd:element name="Boîte" />
<xsd:element name="TrainAV"/>
<xsd:element name="TrainAR"/>
</xsd:sequence>
<xsd:attribute
ref="nb_vitesses"/>
<xsd:attribute ref="type"/>
</xsd:complexType>
<xsd:attribute name="nb_vitesses">
<xsd:annotation>
<xsd:documentation>En comptant la marche
arrière</xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:restriction base="xsd:int">
<xsd:minInclusive
value="4"/>
<xsd:maxInclusive
value="6"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="type">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration
value="automatique"/>
<xsd:enumeration
value="manuelle"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
isbnTypes
définit des suites de n°s ISBN séparés par des blancs.
<?xml version='1.0'?>
<ExpAr>
<Bin op="*">
<Bin op="-">
<VarExp><Var
nom="r"/></VarExp>
<VarExp><Var
nom="b"/></VarExp>
</Bin>
<Bin op="/">
<VarExp> <Var
nom="q"/> </VarExp>
<Bin op="+">
<Bin op="*">
<Cte val="2"/>
<VarExp> <Var
nom="q"/> </VarExp>
</Bin>
<Cte val="1"/>
</Bin>
</Bin>
</Bin>
</ExpAr>
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:simpleType name="opArith">
<xsd:restriction
base="xsd:string">
<xsd:enumeration value="+"/>
<xsd:enumeration value="-"/>
<xsd:enumeration value="*"/>
<xsd:enumeration value="/"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ident">
<xsd:restriction
base="xsd:string">
<xsd:pattern value="[a-z]+"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:element name="Cte">
<xsd:complexType>
<xsd:attribute name="val" type="xsd:integer"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="Var">
<xsd:complexType>
<xsd:attribute name="nom" type="ident"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="VarExp">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="Var"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:group name="Exp">
<xsd:choice>
<xsd:element ref="Cte"/>
<xsd:element ref="VarExp"/>
<xsd:element ref="Bin"/>
</xsd:choice>
</xsd:group>
<xsd:element name="Bin">
<xsd:complexType>
<xsd:sequence>
<xsd:group ref="Exp"/>
<xsd:group ref="Exp"/>
</xsd:sequence>
<xsd:attribute name="op" type="opArith"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="ExpAr">
<xsd:complexType>
<xsd:group ref="Exp"/>
</xsd:complexType>
</xsd:element>
</xsd:schema>
qr.xml
qrd.xml
MIL.xsd
(qui inclut ExpAr.xsd
, naturellement).mesure.xsd
book.xsd
DocumentBuilderFactory dbf =
DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true); // Indispensable
! Voyez le Bréviaire
DOM
/* Si on ne traite pas correctement le namespace,
l'attribut "xsi:noNamespaceSchemaLocation
"cvc-complex-type.3.2.2:
Attribute 'xsi:noNamespaceSchemaLocation' is not allowed to appear in
element 'garage'.
Document doc =
dbf.newDocumentBuilder().parse(fichXML);
Element rac = doc.getDocumentElement();
String fichSchema = "";
if( rac.hasAttributeNS("http://www.w3.org/2001/XMLSchema-instance",
"noNamespaceSchemaLocation") ){
fichSchema
= rac.getAttributeNS("http://www.w3.org/2001/XMLSchema-instance",
"noNamespaceSchemaLocation");
}else{
String acc =
rac.getAttributeNS("http://www.w3.org/2001/XMLSchema-instance",
"schemaLocation");
String[] tacc = acc.split(" ");
fichSchema
= tacc[1];
}
:
validator.validate(new DOMSource(doc)
);
MyValid.java
garage.xml
<?xml
version="1.0" encoding="utf-8" ?>
<garage xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="/Users/jfp/Sites/EPITA/XML09/Cours3/XMLS/VoituresS/garage.xsd"
>
<Voiture marque="Renault" modèle="Safrane">
<Carosserie couleur="rouge">
<Capot>Un peu
cabossé</Capot>
</Carosserie>
<Moteur>
<Cylindres></Cylindres>
<Allumage>Défectueux</Allumage>
</Moteur>
<Transmission type="automatique"
nb_vitesses="6">
<Boîte/>
<TrainAV/>
<TrainAR/>
</Transmission>
</Voiture>
<Voiture marque="Citroën" modèle="CX">
<Carosserie couleur="vert">
<Capot>impeccable</Capot>
</Carosserie>
<Moteur>
<Cylindres></Cylindres>
<Allumage>OK</Allumage>
</Moteur>
<Transmission type="automatique"
nb_vitesses="6">
<Boîte/>
<TrainAV/>
<TrainAR/>
</Transmission>
</Voiture>
<Voiture marque="Fiat" modèle="Panda">
<Carosserie couleur="gris">
<Capot>Endommagé</Capot>
</Carosserie>
<Moteur>
<Cylindres></Cylindres>
<Allumage>Correct</Allumage>
</Moteur>
<Transmission type="manuel" nb_vitesses="5">
<Boîte/>
<TrainAV/>
<TrainAR/>
</Transmission>
</Voiture>
</garage>
garage.xsd
<?xml
version="1.0" encoding="utf-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:include schemaLocation="Voiture-3-0.xsd"/>
<xsd:element name="garage">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Voiture"
type="typVoiture" minOccurs="0" maxOccurs="unbounded" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
jfp% java MyValid VoituresX/garage.xml
Le fichier VoituresX/garage.xml est valide par rapport au schema
/Users/jfp/Sites/EPITA/XML09/Cours3/XMLS/VoituresS/garage.xsd
jfp%
typVoitureExt
ou typVoitureB
.
<?xml version="1.0"?>
<liste
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="/Users/jfp/Sites/EPITA/XML09/Cours3/XMLS/VoituresS/Voiture-3-2.xsd">
<Voiture marque="Renault" modèle="Safrane">
<Carosserie
couleur="rouge">
<Capot>Un peu cabossé</Capot>
</Carosserie>
<Moteur>
<Cylindres></Cylindres>
<Allumage>Défectueux</Allumage>
</Moteur>
<Transmission type="automatique"
nb_vitesses="5">
<Boîte/>
<TrainAV/>
<TrainAR/>
</Transmission>
</Voiture>
<Voiture marque="Renault" modèle="VelSatis" nbPortes="5" xsi:type="typVoitureExt">
<Carosserie
couleur="noire">
<Capot>Impeccable</Capot>
</Carosserie>
<Moteur>
<Cylindres/>
<Allumage>OK</Allumage>
</Moteur>
<Transmission type="automatique"
nb_vitesses="6">
<Boîte/>
<TrainAV/>
<TrainAR/>
</Transmission>
<Genre>berline</Genre>
</Voiture>
<Voiture marque="Renault" modèle="Twingo" xsi:type="typVoitureB">
<Carosserie
couleur="verte">
<Capot>repeint</Capot>
</Carosserie>
<Moteur>
<Cylindres/>
<Allumage>Hésitant</Allumage>
</Moteur>
<Transmission type="manuelle"
nb_vitesses="4">
<Boîte/>
<TrainAV/>
<TrainAR/>
</Transmission>
</Voiture>
</liste>
<?xml version="1.0" encoding="utf-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:include schemaLocation="Voiture-3-0.xsd" />
<xsd:element name="liste">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Voiture" type="typVoiture"
minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:complexType name="typTransB">
<xsd:complexContent>
<xsd:restriction base="typTrans">
<xsd:sequence>
<xsd:element name="Boîte" />
<xsd:element name="TrainAV"/>
<xsd:element name="TrainAR"/>
</xsd:sequence>
<xsd:attribute ref="type" fixed="manuelle"/>
<xsd:attribute ref="nb_vitesses" fixed="4"/>
</xsd:restriction>
</xsd:complexContent>
</xsd:complexType>
<xsd:complexType name ="typVoitureB">
<xsd:complexContent>
<xsd:restriction base="typVoiture">
<xsd:sequence>
<xsd:element ref="Carosserie" />
<xsd:element ref="Moteur" />
<xsd:element name="Transmission" type="typTransB" />
</xsd:sequence>
<xsd:attribute name="marque" type="xsd:string"/>
<xsd:attribute name="modèle" type="xsd:string"/>
</xsd:restriction>
</xsd:complexContent>
</xsd:complexType>
<xsd:complexType name="typVoitureExt">
<xsd:complexContent>
<xsd:extension base="typVoiture">
<xsd:sequence>
<xsd:element ref="Genre"/>
</xsd:sequence>
<xsd:attribute name="nbPortes" type="xsd:integer"/>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
<xsd:element name="Genre">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="berline"/>
<xsd:enumeration value="coupé"/>
<xsd:enumeration value="cabriolet"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
</xsd:schema>
jfp% java MyValid VoituresS/Voiture-3b.xml
Le fichier VoituresS/Voiture-3b.xml est valide par rapport au schema
/Users/jfp/Sites/EPITA/XML09/Cours3/XMLS/VoituresS/Voiture-3-2.xsd
jfp%
nillable
xsd
.xsd:nillable
est un
attribut possible, à valeur booléenne, d'une déclaration de xsd:element
."false"
.nillable="true"
signifie que l'élément
peut être présent mais vide, ne contenant aucune valeur.minoccurs
vaut 0.xsi:nil
,true
".<xsd:element name="intonil"
type="xsd:int" nillable="true" />
<intonil>777</intonil>
et <intonil
xsi:nil="true"/>
sont également valables,nillable="true"
, pour communiquer
la même information il aurait fallu recourir à une valeur<intonil>777</intonil>
et compliquer l'interprétation (problème bien connu !).nillable="true"
et
minoccurs="0"
.null
en Java, nil
ailleurs, quid en XML ?Fichier XML invalide ou
Schema
incorrect : src-include.2.1:
The targetNamespace of the referenced schema, currently
'http://perrot_a.epita/voitures/',
must be identical to that of the including schema, currently
'http://jf.perrot.epita/voitures/'.
Voiture
unique:<?xml
version="1.0"?>
<v:Voiture
xmlns:v="http://jf.perrot.epita/voitures/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=
"http://jf.perrot.epita/voitures/
/Users/jfp/Sites/EPITA/XML09/Cours3/XMLS/VoituresS/Voiture-3-0.ns.xsd"
marque="Renault" modèle="Safrane">
<v:Carosserie couleur="rouge">
<v:Capot>Un peu
cabossé</v:Capot>
</v:Carosserie>
<v:Moteur>
<v:Cylindres/>
<v:Allumage>Défectueux</v:Allumage>
</v:Moteur>
<v:Transmission v:type="automatique"
v:nb_vitesses="6">
<v:Boîte/>
<v:TrainAV/>
<v:TrainAR/>
</v:Transmission>
</v:Voiture>
jfp% java MyValid
VoituresX/Voiture-3.ns.xml
Le fichier VoituresX/Voiture-3.ns.xml est valide par rapport au schema
/Users/jfp/Sites/EPITA/XML09/Cours3/XMLS/VoituresS/Voiture-3-0.ns.xsd
jfp%
jfp% java MyValid
VoituresX/Voiture-3b.ns.xml
ERREUR : 'UndeclaredPrefix: Cannot resolve
'vpe:typVoitureExt' as a QName: the prefix 'vpe' is not declared.'
Fichier XML invalide ou Schema incorrect : UndeclaredPrefix:
Cannot resolve 'vpe:typVoitureExt' as a QName: the prefix 'vpe' is not
declared.
jfp% java -version
java version "1.6.0_07"
Java(TM) SE Runtime Environment (build 1.6.0_07-b06-153)
Java HotSpot(TM) 64-Bit Server VM (build 1.6.0_07-b06-57, mixed mode)
jfp% javac MyValid.java
jfp% java MyValid VoituresX/Voiture-3b.ns.xml
Le fichier VoituresX/Voiture-3b.ns.xml est valide par rapport au schema
/Users/jfp/Sites/EPITA/XML09/Cours3/XMLS/VoituresS/Voiture-3-2.ns.xsd