Поделиться через


Выведение схем из XML-документов

В этом разделе описывается, как использовать класс XmlSchemaInference для выведения схемы XSD из структуры XML-документа.

Процесс выведения схемы

Класс XmlSchemaInference из пространства имен System.Xml.Schema используется для создания одной или нескольких схем XSD из структуры XML-документа. Полученные схемы можно использовать для проверки исходного XML-документа.

Во время обработки XML-документа XmlSchemaInference класс XmlSchemaInference строит предположения о компонентах схемы, описывающих элементы и атрибуты в XML-документе. Класс XmlSchemaInference также выводит компоненты схемы по принципу ограничения - выводится самый строгий тип для каждого элемента или атрибута. По мере сбора дополнительных сведений о XML-документе эти ограничения ослабляются и выводятся менее строгие типы. Наименее строгим выводимым типом является xs:string.

Рассмотрим, например, следующий фрагмент XML-документа.

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

В примере выше, когда в процессе attribute1 обнаруживается атрибут 6 со значением XmlSchemaInference, для него предполагается тип xs:unsignedByte. Когда в процессе parent обнаруживается второй элемент XmlSchemaInference, ограничение ослабляется путем замены типа на xs:string, поскольку теперь атрибут attribute1 имеет значение A. Аналогично, атрибут minOccurs для всех элементов child, выведенных в схему, ослабляется до значения minOccurs="0", поскольку второй родительский элемент не имеет дочерних.

Выведение схем из XML-документов

Класс XmlSchemaInference использует два перегруженных метода InferSchema для вывода схемы из XML-документа.

Первый метод XmlSchemaInference.InferSchema используется для создания схемы на основе XML-документа. Второй метод XmlSchemaInference.InferSchema используется для вывода схемы, описывающей несколько XML-документов. Например, можно по очереди передать методу XmlSchemaInference.InferSchema несколько XML-документов, чтобы создать схему, описывающую весь набор XML-документов.

Первый метод XmlSchemaInference.InferSchema выводит схему из XML-документа, содержащегося в объекте XmlReader, и возвращает объект XmlSchemaSet, содержащий выведенную схему. Второй метод XmlSchemaInference.InferSchema ищет в объекте XmlSchemaSet схему, целевое пространство имен которой совпадает с XML-документом, содержащимся в объекте XmlReader, уточняет существующую схему и возвращает объект XmlSchemaSet, содержащий выведенную схему.

Изменения, вносимые в уточняемую схему, основаны на новой структуре, обнаруженной в XML-документе. Например, в процессе обзора XML-документа строятся предположения об обнаруженных типах данных, и схема создается на основе этих предположений. Однако если во втором проходе выведения обнаруживаются данные, отличающиеся от исходных предположений, схема уточняется. В следующем примере показан процесс уточнения.

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

В примере в качестве первого входного аргумента принимается файл item1.xml.

<?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>

Затем в качестве второго входного аргумента принимается файл item2.xml:

<?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>

Когда в первом XML-документе обнаруживается атрибут productID, для значения 123456789 предполагается тип xs:unsignedInt. Однако, когда при чтении второго XML-документа обнаруживается значение A53-246, тип xs:unsignedInt больше не может предполагаться. Схема уточняется, и тип productID заменяется типом xs:string. Кроме того, атрибут minOccurs для элемента supplierID получает значение 0, поскольку во втором XML-документе отсутствует элемент supplierID.

Далее представлена схема, выведенная из первого XML-документа.

<?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>

Далее представлена схема, выведенная из первого XML-документа и уточненная с помощью второго XML-документа.

<?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>

Встроенные схемы

Если в процессе XmlSchemaInference обнаруживается встроенная схема XSD, создается исключение XmlSchemaInferenceException. Например, следующая встроенная схема вызывает исключение XmlSchemaInferenceException.

<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>  

Неуточняемые схемы

В схемах W3C XML существуют такие конструкции, которые процесс XmlSchemaInference для схемы XSD не может обработать, если задан тип для уточнения, и которые приводят к созданию исключения. Например, сложный тип, на верхнем уровне которого находится компоновщик, отличный от sequence. В модели SOM это соответствует типу XmlSchemaComplexType, свойством Particle которого не является экземпляр XmlSchemaSequence.

См. также