Partager via


Inférence de schémas à partir de documents XML

Cette rubrique décrit comment utiliser la classe XmlSchemaInference pour déduire un schéma en langage XSD (XML Schema Definition) à partir de la structure d'un document XML.

Processus d'inférence du schéma

La classe XmlSchemaInference de l'espace de noms System.Xml.Schema est utilisée pour générer un ou plusieurs schémas en langage XSD à partir de la structure d'un document XML. Les schémas générés peuvent être utilisés pour valider le document XML original.

Lorsqu'un document XML est traité par la classe XmlSchemaInference, la classe XmlSchemaInference fait des hypothèses sur les composants du schéma qui décrivent les éléments et les attributs du document XML. La classe XmlSchemaInference déduit également des composants de schéma de façon contrainte en déduisant le type le plus restrictif d'un élément ou d'un attribut particulier. À mesure que des informations supplémentaires sur le document XML sont collectées, ces contraintes sont assouplies par l'inférence de types moins restrictifs. Le type le moins restrictif qui puisse être déduit est xs:string.

Prenez, par exemple, l'élément suivant d'un document XML.

<parent attribute1="6">
    <child>One</child>
    <child>Two</child>
</parent>
<parent attribute1="A">

Dans l'exemple ci-avant, quand l'attribut attribute1 est rencontré avec une valeur 6 par le processus XmlSchemaInference, il est supposé être du type xs:unsignedByte. Lorsque le second élément parent est rencontré par le processus XmlSchemaInference, la contrainte est assouplie en modifiant le type en xs:string parce que la valeur de l'attribut attribute1 est à présent A. De même, l'attribut minOccurs pour tous les éléments child déduits dans le schéma sont assouplis en minOccurs="0" parce que le second élément parent n'a pas d'élément enfant.

Inférence de schémas à partir de documents XML

La classe XmlSchemaInference utilise deux méthodes InferSchema surchargées pour déduire un schéma à partir d'un document XML.

La première méthode XmlSchemaInference.InferSchema est utilisée pour créer un schéma basé sur un document XML. La seconde méthode XmlSchemaInference.InferSchema est utilisée pour déduire un schéma décrivant plusieurs documents XML. Par exemple, vous pouvez transmettre plusieurs documents XML à la méthode XmlSchemaInference.InferSchema l'un après l'autre afin de produire un schéma décrivant l'ensemble des documents XML.

La première méthode XmlSchemaInference.InferSchema déduit un schéma à partir d'un document XML contenu dans un objet XmlReader et retourne un objet XmlSchemaSet contenant le schéma déduit. La seconde méthode XmlSchemaInference.InferSchema recherche un objet XmlSchemaSet pour un schéma ayant le même nom d'espaces cible que le document XML contenu dans l'objet XmlReader, affine le schéma existant et retourne un objet XmlSchemaSet contenant le schéma déduit.

Les modifications apportées au schéma affiné sont basées sur la nouvelle structure trouvée dans le document XML. Par exemple, lors du parcours d'un document XML, des hypothèses sont faites concernant les types de données rencontrés et le schéma est créé sur la base de ces hypothèses. Toutefois, si des données sont rencontrées lors d'un second cycle d'inférence, qui diffèrent de l'hypothèse initiale, le schéma est affiné. L'exemple suivant illustre le processus d'affinement.

Dim reader As XmlReader = XmlReader.Create("item1.xml")
Dim reader1 As XmlReader = XmlReader.Create("item2.xml")
Dim schemaSet As XmlSchemaSet = New XmlSchemaSet()
Dim inference As XmlSchemaInference = New XmlSchemaInference()
schemaSet = inference.InferSchema(reader)

' Display the inferred schema.
Console.WriteLine("Original schema:\n")
For Each schema As XmlSchema In schemaSet.Schemas("https://www.contoso.com/items")
    schema.Write(Console.Out)
Next

' Use the additional data in item2.xml to refine the original schema.
schemaSet = inference.InferSchema(reader1, schemaSet)

' Display the refined schema.
Console.WriteLine("\n\nRefined schema:\n")
For Each schema As XmlSchema In schemaSet.Schemas("https://www.contoso.com/items")
    schema.Write(Console.Out)
Next
XmlReader reader = XmlReader.Create("item1.xml");
XmlReader reader1 = XmlReader.Create("item2.xml");
XmlSchemaSet schemaSet = new XmlSchemaSet();
XmlSchemaInference inference = new XmlSchemaInference();
schemaSet = inference.InferSchema(reader);

// Display the inferred schema.
Console.WriteLine("Original schema:\n");
foreach (XmlSchema schema in schemaSet.Schemas("https://www.contoso.com/items"))
{
    schema.Write(Console.Out);
}

// Use the additional data in item2.xml to refine the original schema.
schemaSet = inference.InferSchema(reader1, schemaSet);

// Display the refined schema.
Console.WriteLine("\n\nRefined schema:\n");
foreach (XmlSchema schema in schemaSet.Schemas("https://www.contoso.com/items"))
{
    schema.Write(Console.Out);
}
        XmlReader^ reader = XmlReader::Create("item1.xml");
        XmlReader^ reader1 = XmlReader::Create("item2.xml");
        XmlSchemaSet^ schemaSet = gcnew XmlSchemaSet();
        XmlSchemaInference^ inference = gcnew XmlSchemaInference();
        schemaSet = inference->InferSchema(reader);

        // Display the inferred schema.
        Console::WriteLine("Original schema:\n");
        for each (XmlSchema^ schema in schemaSet->Schemas("https://www.contoso.com/items"))
        {
            schema->Write(Console::Out);
        }

        // Use the additional data in item2.xml to refine the original schema.
        schemaSet = inference->InferSchema(reader1, schemaSet);

        // Display the refined schema.
        Console::WriteLine("\n\nRefined schema:\n");
        for each (XmlSchema^ schema in schemaSet->Schemas("https://www.contoso.com/items"))
        {
            schema->Write(Console::Out);
        }

L'exemple prend le fichier item1.xml comme première entrée.

<?xml version="1.0" encoding="utf-8"?>
<item xmlns="https://www.contoso.com/items" productID="123456789">
    <name>Hammer</name>
    <price>9.95</price>
    <supplierID>1929</supplierID>
</item>

L'exemple prend ensuite le fichier item2.xml comme seconde entrée :

<?xml version="1.0" encoding="utf-8"?>
<item xmlns="https://www.contoso.com/items" productID="A53-246">
    <name>Paint</name>
    <price>12.50</price>
</item>

Si l'attribut productID est détecté dans le premier document XML, la valeur 123456789 est supposée être un type xs:unsignedInt. Toutefois, lors de la lecture du second document XML, si la valeur de A53-246 est détectée, l'hypothèse du type xs:unsignedInt n'est plus valable. Le schéma est affiné et le type de productID est changé en xs:string. En outre, l'attribut minOccurs pour l'élément supplierID a la valeur 0 parce que le second document XML ne contient pas d'élément supplierID.

Voici le schéma déduit à partir du premier document XML.

<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="https://www.contoso.com/items" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="item">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="name" type="xs:string" />
        <xs:element name="price" type="xs:decimal" />
        <xs:element name="supplierID" type="xs:unsignedShort" />
      </xs:sequence>
      <xs:attribute name="productID" type="xs:unsignedInt" use="required" />
    </xs:complexType>
  </xs:element>
</xs:schema>

Voici le schéma déduit à partir du premier document XML, affiné par le second document XML.

<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="https://www.contoso.com/items" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="item">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="name" type="xs:string" />
        <xs:element name="price" type="xs:decimal" />
        <xs:element minOccurs="0" name="supplierID" type="xs:unsignedShort" />
      </xs:sequence>
      <xs:attribute name="productID" type="xs:string" use="required" />
    </xs:complexType>
  </xs:element>
</xs:schema>

Schémas inline

Si un schéma en langage XSD (XML Schema Definition) est détecté durant le processus XmlSchemaInference, une exception XmlSchemaInferenceException est levée. Par exemple, le schéma inline suivant lève une exception XmlSchemaInferenceException :

<root xmlns:ex="https://www.contoso.com" xmlns="http://www.tempuri.org">
    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="https://www.contoso.com">
        <xs:element name="Contoso" type="xs:normalizedString" />
    </xs:schema>
    <ex:Contoso>Test</ex:Contoso>
</root>

Schémas qui ne peuvent pas être affinés

Il y a trois constructions de schéma XML conformes aux spécifications du W3C que le processus XmlSchemaInference de schéma en langage XSD ne peut pas gérer s'il reçoit un type particulier à affiner, et qui entraînent la levée d'une exception. Il peut s'agir, par exemple, d'un type complexe dont le constructeur de niveau supérieur n'est pas une séquence. Dans le Modèle Objet du schéma (SOM), cela correspond à un objet XmlSchemaComplexType dont la propriété Particle n'est pas une instance de l'objet XmlSchemaSequence.

Voir aussi

Référence

XmlSchemaInference

Concepts

Inférence d'un schéma XML

Règles pour l'inférence de types et de structure de nœud de schéma

Règles relatives à l'inférence de types simples

Autres ressources

Modèle Objet du schéma (SOM) XML