Les fichiers XML Schema Definition (XSD) permettent de décrire la structure d’un document XML. Le grand intérêt de ce fichier est de servir à la validation du document XML en définisant des règles.
Génération automatique d’un fichier XSD à partir d’un fichier XML
Avec Xsd.exe
Cet outil fait partie du SDK Visual Studio. Il est accessible en utilisant une ligne de commandes dans le répertoire du SDK, par exemple:
C:\Program Files\Microsoft Visual Studio 9.0\SDK\v2.0\Bin
Pour générer le fichier XSD, il suffit d’écrire:
xsd [chemin du fichier XML] /outputdir:[répertoire où générer le fichier XSD]
Par exemple:
xsd fichier.xml /outputdir:"C:\MonRepertoire"
Par programmation
Le code suivant permet de générer un fichier XSD par programmation:
using System.Xml;
using System.Xml.Schema;
...
public void WriteXsd(string xmlFilePath)
{
XmlReader reader = XmlReader.Create(xmlFilePath);
XmlSchemaInference schema = new XmlSchemaInference();
XmlSchemaSet schemaSet = schema.InferSchema(reader);
foreach (XmlSchema s in schemaSet.Schemas())
{
using (var stringWriter = new StringWriter())
{
using (var writer = XmlWriter.Create(stringWriter))
{
s.Write(writer);
}
textbox.text = stringWriter.ToString();
}
}
}
Validation d’un fichier XML
Par programmation
Avec XmlSchemaSet
L’avantage de cette méthode est d’être utilisable à partir du Framework 2.0.
Un fichier XML peut être lu et validé de cette façon:
using System;
using System.Xml;
using System.Xml.Schema;
...
public void ValidateXmlFile(string schemaNamespace, string xsdFilePath, string xmlFilePath)
{
XmlReaderSettings settings = new XmlReaderSettings();
settings.Schemas.Add(schemaNamespace, xsdFilePath);
settings.ValidationType = ValidationType.Schema;
settings.ValidationEventHandler += new ValidationEventHandler(
validationCallBack);
XmlReader readItems = XmlReader.Create(xmlFilePath, settings);
while (readItems.Read()) { }
}
private void validationCallBack(object sender, ValidationEventArgs e)
{
if (e.Severity.Equals(XmlSeverityType.Warning))
{
Console.Write("WARNING: ");
Console.WriteLine(e.Message);
}
else if (e.Severity.Equals(XmlSeverityType.Error))
{
Console.Write("ERROR: ");
Console.WriteLine(e.Message);
}
}
Ce code permet de valider un fichier XML suivant le schéma défini dans un fichier XSD. La validation s’effectue dans le namespace indiqué par le paramètre “schemaNamespace”.
Plus de détails sur MSDN.
Il est possible d’indiquer des critères suivant lesquels la validation sera effectuée.
Par exemple:
XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidationType = ValidationType.Schema;
settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessInlineSchema;
settings.ValidationFlags |= XmlSchemaValidationFlags.ReportValidationWarnings;
settings.ValidationEventHandler += new ValidationEventHandler (ValidationCallBack);
XmlSchemaValidationFlags.ProcessInlineSchema
indique la validation traite des schémas inline trouvés. Les schémas inline étant des définitions inclues directement à l’intérieur de l’instance du fichier XML.
XmlSchemaValidationFlags.ReportValidationWarnings
permet de signaler les avertissements de validation.
D’autres critères sont possibles pour l’enum XmlSchemaValidationFlags.
Plus de détails à propos de XmlReaderSettings.ValidationFlags
sur MSDN.
Avec XDocument (LinQ to XML)
Cette méthode est possible à partir du Framework 3.5:
using System;
using System.Xml;
using System.Xml.Linq;
...
public void ValidateXmlFile(string schemaNamespace, string xsdFilePath, string xmlFilePath)
{
XmlSchemaSet schemas = new XmlSchemaSet();
schemas.Add(schemaNamespace, xsdFilePath);
XDocument doc = XDocument.Load(xmlFilePath);
string validationFeedbackMessage = string.Empty;
doc.Validate(schemas, (objectSender, validationEventArgs) => {
validationFeedbackMessage += validationEventArgs.Message + Environment.NewLine;
});
Console.WriteLine(msg == "" ? "Document is valid" : "Document invalid: " + validationFeedbackMessage);
}
Plus de détails à propos de ce type de validation sur MSDN.
A la compilation dans Visual Studio
Il est possible d’effectuer la validation d’un fichier XML à la compilation dans Visual Studio. Cette validation peut être pratique, par exemple, après avoir édité un fichier de configuration.
La validation s’effectue aussi lorsqu’on édite le fichier.
Cette fonctionnalité est disponible à partir de Visual Studio 2008. Pour l’utiliser, il faut:
1. Ajouter le fichier XML au projet
2. Ajouter le fichier XSD au projet
3. Faire un clique droit sur le fichier XML puis "Properties".
4. Cliquer sur les "…" du paramètre "Schemas".
5. Cliquer dans la colonne "Use" pour les lignes correspondant aux fichiers XSD à utiliser.
Voir plus bas pour plus de détails
Explication sur les "namespaces"
Les fichiers de schéma XSD utilisent des espaces de noms (i.e. "namespaces") pour distinguer les éléments appartenant au langage XSD et les éléments et attributs définis pour un schéma donné.
Dans l’en-tête d’un fichier XSD, on précise:
– le namespace des éléments appartenant au langage XSD
– si besoin, le namespace des éléments et attributs que l’on s’apprête à définir.
Namespace des éléments appartenant au langage XSD
On définit le namespace des éléments appartenant au langage XSD, on indique dans le fichier XSD:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
...
</xs:schema>
xmlns
signifie "xml namespace". xs
est le préfixe utilisé pour éléments XSD.
Parfois on peut utiliser le préfixe xsd
, dans ce cas le schéma sera défini par:
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
...
</xsd:schema>
Définir le namespace des éléments du schéma
On peut indiquer un namespace pour les éléments que l’on va définir dans le fichier XSD. Cette indication est facultative mais elle permet d’éviter les confusions. Ainsi on rajoute les attributs:
targetNamespace="http://yourdomain.org/namespace/" xmlns:this="http://yourdomain.org/namespace/"
.
targetNamespace
est le namespace et xmlns:this
précise le préfixe utilisé (qui sera “this”).
Si on définit le fichier XSD suivant:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://yourdomain.com/namespace/"
xmlns:this="http://yourdomain.com/namespace/">
...
</xs:schema>
Alors pour faire référence à des éléments définis, il faut utiliser le préfixe "this". Par exemple, si on définit l’élément "Row" de cette façon:
<xs:complexType name="Row">
<xs:sequence>
<xs:element name="Name" type="xs:string" minOccurs="1" maxOccurs="1" />
<xs:element name="Value" type="xs:float" minOccurs="1" maxOccurs="1" />
</xs:sequence>
</xs:complexType>
Pour faire référence à cet élément dans le reste du fichier XSD, il faut utiliser le préfixe:
<xs:element name="Rows" type="this:Row" minOccurs="0" maxOccurs="unbounded" />
Ce préfixe est utilisé au niveau du fichier XSD. On n’est pas obligé d’utiliser le même préfixe dans le fichier XML car il est redéfinit dans l’en-tête du fichier XML.
Par exemple, dans le cas précédent si on supprime le préfixe, le fichier XSD sera:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://yourdomain.com/namespace/"
xmlns="http://yourdomain.com/namespace/">
...
</xs:schema>
elementFormDefault
On utilise cet attribut pour indiquer si les éléments du namespace doivent être qualifiés ou non en utlisant le préfixe du namespace dans le fichier XML. Les 2 valeurs possibles sont: "qualified" et "unqualified". Par exemple, si on considère les éléments suivants définis dans un fichier XSD:
<xs:complexType name="AuthorType">
<xs:sequence>
<xs:element name="name" type="xs:string"/>
<xs:element name="phone" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:element name="author" type="this:AuthorType"/>
elementFormDefault="qualified"
Les éléments définis doivent être préfixés. Donc dans le fichier XML, on devra préfixer tous les éléments de l’instance (par forcément avec le même préfixe que dans le fichier XSD puisqu’on redéfinit le préfixe):
<x:author xmlns:x="http://example.org/publishing">
<x:name>Aaron Skonnard</name>
<x:phone>(801)390-4552</phone>
</x:author>
elementFormDefault="unqualified"
Il n’est pas nécessaire de préfixer tous les éléments de l’instance:
<x:author xmlns:x="http://example.org/publishing">
<name>Aaron Skonnard</name>
<phone>(801)390-4552</phone>
</x:author>
Généralement, on impose la présence du préfixe en utilisant la valeur "qualified" dans le fichier XSD:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://yourdomain.com/namespace/"
xmlns:this="http://yourdomain.com/namespace/"
elementFormDefault="qualified">
...
</xs:schema>
Association du fichier XML avec le fichier XSD
Un fichier XML dont les éléments sont définis dans un fichier XSD est considéré comme un document instance. Dans le fichier XML, on utilise l’attribut xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
pour désigner cette instance.
On utilise ensuite l’attribut xsi
pour indiquer le fichier XSD définissant les éléments du fichier XML.
Si on n’utilise pas de namespaces
Rien n’oblige à utiliser des namespaces. Dans ce cas, dans le fichier XML on utilise l’attribut xsi:noNamespaceSchemaLocation
.
Par exemple, si on considère le fichier XSD:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
<xs:element name="Rows" type="Row" minOccurs="0" maxOccurs="unbounded" />
...
</xs:schema>
Le fichier XML pourrait être:
<?xml version="1.0" encoding="UTF-8" ?>
<Rows
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="schemaFile.xsd">
...
</Rows>
Si on utilise des namespaces
Dans le fichier XML, en plus de l’attribut xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
qui permet de préciser l’instance, il faut utiliser:
– xsi:schemaLocation
pour indiquer le fichier XSD
– redéfinir le ou les namespaces utilisés avec, par exemple, un attribut: xmlns:this="http://yourdomain.com/namespace/"
(on est pas obligé d’utiliser le même préfixe que pour le fichier XSD).
Par exemple si on définit le fichier XSD de la façon suivante:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://yourdomain.com/namespace/"
xmlns:this="http://yourdomain.com/namespace/"
elementFormDefault="qualified">
...
</xs:schema>
Le fichier XML correspondant pourrait être:
<?xml version="1.0" encoding="UTF-8" ?>
<Rows
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://yourdomain.com/namespace/ schemaFile.xsd"
xmlns:this="http://yourdomain.com/namespace/">
...
</Rows>
Le préfixe "this" n’est pas obligatoire et n’est pas forcément le même que celui du fichier XSD.
- Aide-mémoire fichier XSD: http://www.tutorialspoint.com/xsd/index.htm
- XML Schema Definition Tool (Xsd.exe): https://msdn.microsoft.com/en-us/library/x6c1kb0s%28v=vs.110%29.aspx
- Create XSD from XML in Code: http://stackoverflow.com/questions/22835730/create-xsd-from-xml-in-code
- How to: Validate Using XSD (LINQ to XML): https://msdn.microsoft.com/en-us/library/bb387037%28v=vs.110%29.aspx
- XML Schema (XSD) Validation with XmlSchemaSet: https://msdn.microsoft.com/en-us/library/3740e0b5%28v=vs.110%29.aspx
- XSD Validation in Visual Studio: http://stackoverflow.com/questions/3161224/xml-validation-with-xsd-in-visual-studio-ide
- Structurez vos données avec XML: https://openclassrooms.com/courses/structurez-vos-donnees-avec-xml/schema-xml-introduction
- XSD structure du fichier et espaces de nom= http://tecfa.unige.ch/guides/tie/html/xml-schema/xml-schema-3.html
- XSD The schema element: http://www.w3schools.com/xml/schema_schema.asp
- XML Schema Tutorial: https://www.liquid-technologies.com/xml-schema-tutorial/xsd-namespaces
- Introduction aux schémas W3C XML Schema: http://xmlfr.org/documentations/tutoriels/001218-0001