Freigeben über


Herleiten von Schemata aus XML-Dokumenten

In diesem Thema wird beschrieben, wie die XmlSchemaInference-Klasse zum Herleiten eines XSD-Schemas (XML Schema Definition Language) aus der Struktur eines XML-Dokuments verwendet wird.

Der Schemarückschlussprozess

Die XmlSchemaInference-Klasse des System.Xml.Schema-Namespaces wird verwendet, um mindestens ein XSD-Schema (XML Schema Definition Language) aus der Struktur eines XML-Dokuments herzuleiten. Die generierten Schemata können zum Validieren des ursprünglichen XML-Dokuments verwendet werden.

Da ein XML-Dokument von der XmlSchemaInference-Klasse verarbeitet wird, bestehen seitens der XmlSchemaInference-Klasse Einschränkungen hinsichtlich der Schemakomponenten, die die Elemente und Attribute im XML-Dokument beschreiben. Die XmlSchemaInference-Klasse leitet Schemakomponenten auch nur eingeschränkt her, indem sie für ein bestimmtes Element oder Attribut den eingeschränktesten Typ herleitet. Da weitere Informationen zum XML-Dokument erfasst werden, werden die Einschränkungen zunehmend aufgehoben, indem weniger eingeschränkte Typen hergeleitet werden. Der Typ mit der geringsten Einschränkung, der hergeleitet wird, ist xs:string.

Betrachten Sie beispielsweise den folgenden Teil eines XML-Dokuments.

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

Im obigen Beispiel wird angenommen, dass das Attribut dem Typ attribute1 angehört, wenn der 6-Prozess das XmlSchemaInference-Attribut mit dem Wert xs:unsignedByte ermittelt. Wenn das zweite parent-Element vom XmlSchemaInference-Prozess ermittelt wird, wird die Einschränkung zunehmend aufgehoben, indem der Typ xs:string geändert wird, da der Wert des attribute1-Attributs jetzt A ist. Das minOccurs-Attribut für alle im Schema hergeleiteten child-Elemente wird in ähnlicher Weise bis zu minOccurs="0" gelockert, da das zweite direkt übergeordnete Element nicht über direkt untergeordnete Elemente verfügt.

Herleiten von Schemata aus XML-Dokumenten

Die XmlSchemaInference-Klasse verwendet zwei überladene InferSchema-Methoden, um ein Schema aus einem XML-Dokument herzuleiten.

Die erste XmlSchemaInference.InferSchema-Methode wird verwendet, um ein auf ein XML-Dokument beruhendes Schema zu erstellen. Die zweite XmlSchemaInference.InferSchema-Methode wird verwendet, um ein Schema herzuleiten, das mehrere XML-Dokumente beschreibt. Sie können beispielsweise mehrere XML-Dokumente nacheinander an die XmlSchemaInference.InferSchema-Methode übertragen, um ein Schema zu erstellen, dass die gesamte Gruppe von XML-Dokumenten beschreibt.

Die erste XmlSchemaInference.InferSchema-Methode leitet ein Schema aus einem XML-Dokument her, das in einem XmlReader-Objekt enthalten ist, und gibt ein XmlSchemaSet-Objekt zurück, das das hergeleitete Schema enthält. Die zweite XmlSchemaInference.InferSchema-Methode sucht ein XmlSchemaSet-Objekt für ein Schema mit demselben Zielnamespace wie das XML-Dokument, das im XmlReader-Objekt enthalten ist. Sie präzisiert das vorhandene Schema und gibt ein XmlSchemaSet-Objekt zurück, das das hergeleitete Schema enthält.

Die Änderungen am präzisierten Schema beruhen auf der neuen im XML-Dokument gefundenen Struktur. Wenn beispielsweise ein XML-Dokument durchlaufen wird, werden Vermutungen über die gefundenen Datentypen angestellt, und das Schema wird auf der Grundlage dieser Vermutungen erstellt. Wenn jedoch bei einer zweiten Herleitungsübergabe Daten ermittelt werden, die nicht mit der ursprünglichen Vermutung übereinstimmen, wird das Schema präzisiert. Im folgenden Beispiel wird der Präzisierungsvorgang veranschaulicht.

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("http://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("http://www.contoso.com/items"))
{
    schema->Write(Console::Out);
}
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("http://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("http://www.contoso.com/items"))
{
    schema.Write(Console.Out);
}
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("http://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("http://www.contoso.com/items")
    schema.Write(Console.Out)
Next

In diesem Beispiel wird die folgende Datei, item1.xml, als erste Eingabe verwendet.

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

Im Beispiel wird dann die Datei item2.xml als zweite Eingabe verwendet:

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

Wenn das productID-Attribut im ersten XML-Dokument ermittelt wird, wird angenommen, dass der Wert 123456789 dem Typ xs:unsignedInt angehört. Wenn jedoch das zweite XML-Dokument gelesen und der Wert A53-246 gefunden wird, kann nicht mehr davon ausgegangen werden, dass es sich um den xs:unsignedInt-Typ handelt. Das Schema wird präzisiert, und der Typ productID wird in xs:string geändert. Außerdem wird das minOccurs-Attribut für das supplierID-Element auf 0 festgelegt, da das zweite XML-Dokument kein supplierID-Element enthält.

Im Folgenden wird das aus dem ersten XML-Dokument hergeleitete Schema dargestellt.

<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://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>

Im Folgenden wird das Schema dargestellt, das aus dem ersten XML-Dokument hergeleitet und durch das zweite XML-Dokument präzisiert wurde.

<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://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>

Inlineschemata

Wenn während des XmlSchemaInference-Prozesses ein XSD-Schema (XML Schema Definition Language) ermittelt wurde, wird eine XmlSchemaInferenceException ausgelöst. Das folgende Inlineschema löst beispielsweise eine XmlSchemaInferenceException aus.

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

Nicht präzisierbare Schemata

Es existieren XML-Schemakonstrukte des W3C, die der XmlSchemaInference-Prozess für das XSD-Schema (XML Schema Definition Language) nicht behandeln kann, wenn ein Typ zum Präzisieren und zum Hervorrufen einer auszulösenden Ausnahme vorhanden ist. Dabei handelt es sich um einen komplexen Typ, dessen Compositor auf der obersten Ebene keine Folge ist. In einem SOM (Schemaobjektmodell) entspricht dies einem XmlSchemaComplexType, dessen Particle-Eigenschaft keine Instanz von XmlSchemaSequence ist.

Siehe auch