Compartir a través de


Inferir esquemas a partir de documentos XML

En este tema se describe cómo usar la XmlSchemaInference clase para deducir un esquema del lenguaje de definición de esquemas XML (XSD) a partir de la estructura de un documento XML.

Proceso de inferencia de esquema

La XmlSchemaInference clase del System.Xml.Schema espacio de nombres se usa para generar uno o varios esquemas del lenguaje de definición de esquemas XML (XSD) a partir de la estructura de un documento XML. Los esquemas generados se pueden usar para validar el documento XML original.

A medida que la XmlSchemaInference clase procesa un documento XML, la XmlSchemaInference clase realiza suposiciones sobre los componentes de esquema que describen los elementos y atributos del documento XML. La XmlSchemaInference clase también deduce los componentes de esquema de una manera restringida mediante la inferencia del tipo más restrictivo para un elemento o atributo determinado. A medida que se recopila más información sobre el documento XML, estas restricciones se suavizan mediante la inferencia de tipos menos restrictivos. El tipo menos restrictivo que se puede deducir es xs:string.

Tome, por ejemplo, la siguiente parte de un documento XML.

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

En el ejemplo anterior, cuando el proceso attribute1 encuentra el atributo 6 con un valor de XmlSchemaInference, se asume que es de tipo xs:unsignedByte. Cuando el proceso parent encuentra el segundo elemento XmlSchemaInference, la restricción se afloja modificando el tipo a xs:string porque el valor del atributo attribute1 es ahora A. Del mismo modo, el atributo minOccurs de todos los elementos child inferidos en el esquema se relajan a minOccurs="0" porque el segundo elemento primario no tiene elementos secundarios.

Inferencia de esquemas de documentos XML

La XmlSchemaInference clase usa dos métodos sobrecargados InferSchema para deducir un esquema de un documento XML.

El primer XmlSchemaInference.InferSchema método se usa para crear un esquema basado en un documento XML. El segundo XmlSchemaInference.InferSchema método se usa para deducir un esquema que describe varios documentos XML. Por ejemplo, puede proporcionar varios documentos XML al XmlSchemaInference.InferSchema método uno a uno para generar un esquema que describa todo el conjunto de documentos XML.

El primer XmlSchemaInference.InferSchema método deduce un esquema de un documento XML contenido en un XmlReader objeto y devuelve un XmlSchemaSet objeto que contiene el esquema inferido. El segundo XmlSchemaInference.InferSchema método busca un XmlSchemaSet objeto para un esquema con el mismo espacio de nombres de destino que el documento XML contenido en el XmlReader objeto, refina el esquema existente y devuelve un XmlSchemaSet objeto que contiene el esquema inferido.

Los cambios realizados en el esquema refinado se basan en una nueva estructura que se encuentra en el documento XML. Por ejemplo, a medida que se recorre un documento XML, se realizan suposiciones sobre los tipos de datos encontrados y el esquema se crea en función de esas suposiciones. Sin embargo, si se encuentran datos en un segundo paso de inferencia que difiere de la suposición original, el esquema se refina. En el ejemplo siguiente se muestra el proceso de refinamiento.

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

En el ejemplo se toma el siguiente archivo, item1.xml, como su primera entrada.

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

A continuación, en el ejemplo se toma el item2.xml archivo como segunda entrada:

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

Cuando se encuentra el productID atributo en el primer documento XML, se supone que el valor de 123456789 es un xs:unsignedInt tipo. Sin embargo, cuando se lee el segundo documento XML y se encuentra el valor de A53-246 , ya no se puede asumir el xs:unsignedInt tipo. El esquema se refina y el tipo de productID se cambia a xs:string. Además, el atributo minOccurs del elemento supplierID se establece en 0, porque el segundo documento XML no contiene ningún elemento supplierID.

A continuación se muestra el esquema inferido del primer documento 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>

A continuación se muestra el esquema inferido del primer documento XML, refinado por el segundo documento 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>

Esquemas insertados

Si se encuentra un esquema de lenguaje de definición de esquema XML insertado (XSD) durante el XmlSchemaInference proceso, se produce una XmlSchemaInferenceException excepción . Por ejemplo, el siguiente esquema en línea lanza un 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>

Esquemas que no se pueden refinar

Hay construcciones de esquema XML de W3C que el proceso de esquema del lenguaje de definición de esquemas XML (XSD) XmlSchemaInference no puede manejar si se proporciona un tipo para refinar, lo que provoca que se produzca una excepción. Por ejemplo, un tipo complejo cuyo compositor de nivel superior es cualquier otro que no sea una secuencia. En el Modelo de objetos de esquema (SOM), corresponde a una XmlSchemaComplexType cuya Particle propiedad no es una instancia de XmlSchemaSequence.

Consulte también