Выведение схем из 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.