从 XML 文档推断架构

本主题介绍如何使用 XmlSchemaInference 类从 XML 文档的结构推断 XML 架构定义语言 (XSD) 架构。

模式推理过程

命名空间 XmlSchemaInferenceSystem.Xml.Schema 类用于从 XML 文档的结构生成一个或多个 XML 架构定义语言(XSD)。 生成的架构可用于验证原始 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 文档的架构。 例如,可以将多个 XML 文档一次馈送给 XmlSchemaInference.InferSchema 一个方法,以生成描述整个 XML 文档集的架构。

第一 XmlSchemaInference.InferSchema 种方法从对象中包含的 XmlReader XML 文档推断架构,并返回 XmlSchemaSet 包含推断架构的对象。 第二 XmlSchemaInference.InferSchema 种方法是在 XmlSchemaSet 对象中搜索与 XmlReader 对象中包含的 XML 文档具有相同目标命名空间的模式,改进现有模式,并返回一个包含推断模式的 XmlSchemaSet 对象。

对精简架构所做的更改基于 XML 文档中找到的新结构。 例如,在遍历 XML 文档时,会基于这些假设对找到的数据类型进行假设,并且会基于这些假设创建架构。 但是,如果在进行第二次推理时遇到与原始假设不同的数据,则会优化模式。 以下示例演示优化过程。

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 过程中遇到内联 XML 架构定义语言 (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>

无法优化的架构

如果给定一个类型进行细化,那么 XML 架构定义语言 (XSD) 架构进程无法处理 W3C XML 模式 XmlSchemaInference 构造,并会导致抛出异常。 例如一种复杂类型,其顶级合成器是序列以外的任何内容。 在架构对象模型(SOM)中,这对应于一个 ,其属性不是 的实例。

另请参阅