Validación de un documento XML en el DOM

La clase XmlDocument no valida el código XML en el Modelo de objetos de documento (DOM) con un esquema del lenguaje de definición de esquemas XML (XSD) ni una definición de tipo de documento (DTD) de manera predeterminada; solo se comprueba si el código XML es correcto.

Para validar el código XML en el DOM, puede validarlo a medida que se carga en el DOM pasando un XmlReader de validación de esquemas al método Load de la clase XmlDocument, o bien validar en el DOM un documento XML que no estuviera validado previamente utilizando el método Validate de la clase XmlDocument.

Validación de un documento XML a medida que se carga en el DOM

La clase XmlDocument valida los datos XML a medida que se cargan en el DOM cuando se pasa un XmlReader de validación al método Load de la clase XmlDocument.

Después de realizar la validación correctamente, se aplican los valores predeterminados del esquema, los valores de texto se convierten en valores atómicos como sea preciso y la información de tipos se asocia a los elementos de información validados. Como resultado, los datos XML con tipo reemplazan a los datos XML sin tipo anteriores.

Creación de un XmlReader de validación de esquemas XML

Para crear un XmlReader de validación de esquemas XML, siga estos pasos.

  1. Cree una nueva instancia de XmlReaderSettings.

  2. Agregue un esquema XML a la propiedad Schemas de la instancia XmlReaderSettings.

  3. Especifique Schema como ValidationType.

  4. Opcionalmente, especifique ValidationFlags y ValidationEventHandler para que controlen las advertencias y errores de validación de esquemas que se encuentren durante la validación.

  5. Por último, pase el objeto XmlReaderSettings al método Create de la clase XmlReader junto con el documento XML, para crear un XmlReader de validación de esquemas.

Ejemplo

En el siguiente código de ejemplo, un XmlReader de validación de esquemas valida los datos XML cargados en el DOM. Se realizan modificaciones no válidas en el documento XML y, a continuación, dicho documento se vuelve a validar, lo que produce errores de validación del esquema. Por último, se corrige uno de los errores y, a continuación, se valida parcialmente parte del documento XML.

#using <System.Xml.dll>

using namespace System;
using namespace System::Xml;
using namespace System::Xml::Schema;

ref class XmlDocumentValidationExample
{
public:

    static void Main()
    {
        try
        {
            // Create a schema validating XmlReader.
            XmlReaderSettings^ settings = gcnew XmlReaderSettings();
            settings->Schemas->Add("http://www.contoso.com/books", "contosoBooks.xsd");
            ValidationEventHandler^ eventHandler = gcnew ValidationEventHandler(ValidationEventHandlerOne);
            settings->ValidationEventHandler += eventHandler;
            settings->ValidationFlags = settings->ValidationFlags | XmlSchemaValidationFlags::ReportValidationWarnings;
            settings->ValidationType = ValidationType::Schema;

            XmlReader^ reader = XmlReader::Create("contosoBooks.xml", settings);

            // The XmlDocument validates the XML document contained
            // in the XmlReader as it is loaded into the DOM.
            XmlDocument^ document = gcnew XmlDocument();
            document->Load(reader);

            // Make an invalid change to the first and last 
            // price elements in the XML document, and write
            // the XmlSchemaInfo values assigned to the price
            // element during load validation to the console.
            XmlNamespaceManager^ manager = gcnew XmlNamespaceManager(document->NameTable);
            manager->AddNamespace("bk", "http://www.contoso.com/books");

            XmlNode^ priceNode = document->SelectSingleNode("/bk:bookstore/bk:book/bk:price", manager);

            Console::WriteLine("SchemaInfo.IsDefault: {0}", priceNode->SchemaInfo->IsDefault);
            Console::WriteLine("SchemaInfo.IsNil: {0}", priceNode->SchemaInfo->IsNil);
            Console::WriteLine("SchemaInfo.SchemaElement: {0}", priceNode->SchemaInfo->SchemaElement);
            Console::WriteLine("SchemaInfo.SchemaType: {0}", priceNode->SchemaInfo->SchemaType);
            Console::WriteLine("SchemaInfo.Validity: {0}", priceNode->SchemaInfo->Validity);

            priceNode->InnerXml = "A";

            XmlNodeList^ priceNodes = document->SelectNodes("/bk:bookstore/bk:book/bk:price", manager);
            XmlNode^ lastprice = priceNodes[priceNodes->Count - 1];
            
            lastprice->InnerXml = "B";

            // Validate the XML document with the invalid changes.
            // The invalid changes cause schema validation errors.
            document->Validate(eventHandler);

            // Correct the invalid change to the first price element.
            priceNode->InnerXml = "8.99";

            // Validate only the first book element. The last book
            // element is invalid, but not included in validation.
            XmlNode^ bookNode = document->SelectSingleNode("/bk:bookstore/bk:book", manager);
            document->Validate(eventHandler, bookNode);
        }
        catch (XmlException^ ex)
        {
            Console::WriteLine("XmlDocumentValidationExample.XmlException: {0}", ex->Message);
        }
        catch(XmlSchemaValidationException^ ex)
        {
            Console::WriteLine("XmlDocumentValidationExample.XmlSchemaValidationException: {0}", ex->Message);
        }
        catch (Exception^ ex)
        {
            Console::WriteLine("XmlDocumentValidationExample.Exception: {0}", ex->Message);
        }
    }

    static void ValidationEventHandlerOne(Object^ sender, ValidationEventArgs^ args)
    {
        if (args->Severity == XmlSeverityType::Warning)
            Console::Write("\nWARNING: ");
        else if (args->Severity == XmlSeverityType::Error)
            Console::Write("\nERROR: ");

        Console::WriteLine(args->Message);
    }
};

int main()
{
    XmlDocumentValidationExample::Main();
    return 0;
}
using System;
using System.Xml;
using System.Xml.Schema;

class XmlDocumentValidationExample
{
    static void Main(string[] args)
    {
        try
        {
            // Create a schema validating XmlReader.
            XmlReaderSettings settings = new XmlReaderSettings();
            settings.Schemas.Add("http://www.contoso.com/books", "contosoBooks.xsd");
            settings.ValidationEventHandler += new ValidationEventHandler(ValidationEventHandler);
            settings.ValidationFlags = settings.ValidationFlags | XmlSchemaValidationFlags.ReportValidationWarnings;
            settings.ValidationType = ValidationType.Schema;

            XmlReader reader = XmlReader.Create("contosoBooks.xml", settings);

            // The XmlDocument validates the XML document contained
            // in the XmlReader as it is loaded into the DOM.
            XmlDocument document = new XmlDocument();
            document.Load(reader);

            // Make an invalid change to the first and last
            // price elements in the XML document, and write
            // the XmlSchemaInfo values assigned to the price
            // element during load validation to the console.
            XmlNamespaceManager manager = new XmlNamespaceManager(document.NameTable);
            manager.AddNamespace("bk", "http://www.contoso.com/books");

            XmlNode priceNode = document.SelectSingleNode(@"/bk:bookstore/bk:book/bk:price", manager);

            Console.WriteLine("SchemaInfo.IsDefault: {0}", priceNode.SchemaInfo.IsDefault);
            Console.WriteLine("SchemaInfo.IsNil: {0}", priceNode.SchemaInfo.IsNil);
            Console.WriteLine("SchemaInfo.SchemaElement: {0}", priceNode.SchemaInfo.SchemaElement);
            Console.WriteLine("SchemaInfo.SchemaType: {0}", priceNode.SchemaInfo.SchemaType);
            Console.WriteLine("SchemaInfo.Validity: {0}", priceNode.SchemaInfo.Validity);

            priceNode.InnerXml = "A";

            XmlNodeList priceNodes = document.SelectNodes(@"/bk:bookstore/bk:book/bk:price", manager);
            XmlNode lastprice = priceNodes[priceNodes.Count - 1];

            lastprice.InnerXml = "B";

            // Validate the XML document with the invalid changes.
            // The invalid changes cause schema validation errors.
            document.Validate(ValidationEventHandler);

            // Correct the invalid change to the first price element.
            priceNode.InnerXml = "8.99";

            // Validate only the first book element. The last book
            // element is invalid, but not included in validation.
            XmlNode bookNode = document.SelectSingleNode(@"/bk:bookstore/bk:book", manager);
            document.Validate(ValidationEventHandler, bookNode);
        }
        catch (XmlException ex)
        {
            Console.WriteLine("XmlDocumentValidationExample.XmlException: {0}", ex.Message);
        }
        catch(XmlSchemaValidationException ex)
        {
            Console.WriteLine("XmlDocumentValidationExample.XmlSchemaValidationException: {0}", ex.Message);
        }
        catch (Exception ex)
        {
            Console.WriteLine("XmlDocumentValidationExample.Exception: {0}", ex.Message);
        }
    }

    static void ValidationEventHandler(object sender, System.Xml.Schema.ValidationEventArgs args)
    {
        if (args.Severity == XmlSeverityType.Warning)
            Console.Write("\nWARNING: ");
        else if (args.Severity == XmlSeverityType.Error)
            Console.Write("\nERROR: ");

        Console.WriteLine(args.Message);
    }
}
Imports System.Xml
Imports System.Xml.Schema

Class XmlDocumentValidationExample

    Shared Sub Main()

        Try

            ' Create a schema validating XmlReader.
            Dim settings As XmlReaderSettings = New XmlReaderSettings()
            settings.Schemas.Add("http://www.contoso.com/books", "contosoBooks.xsd")
            AddHandler settings.ValidationEventHandler, New ValidationEventHandler(AddressOf ValidationEventHandler)
            settings.ValidationFlags = settings.ValidationFlags And XmlSchemaValidationFlags.ReportValidationWarnings
            settings.ValidationType = ValidationType.Schema

            Dim reader As XmlReader = XmlReader.Create("contosoBooks.xml", settings)

            ' The XmlDocument validates the XML document contained
            ' in the XmlReader as it is loaded into the DOM.
            Dim document As XmlDocument = New XmlDocument()
            document.Load(reader)

            ' Make an invalid change to the first and last 
            ' price elements in the XML document, and write
            ' the XmlSchemaInfo values assigned to the price
            ' element during load validation to the console.
            Dim manager As XmlNamespaceManager = New XmlNamespaceManager(document.NameTable)
            manager.AddNamespace("bk", "http://www.contoso.com/books")

            Dim priceNode As XmlNode = document.SelectSingleNode("/bk:bookstore/bk:book/bk:price", manager)

            Console.WriteLine("SchemaInfo.IsDefault: {0}", priceNode.SchemaInfo.IsDefault)
            Console.WriteLine("SchemaInfo.IsNil: {0}", priceNode.SchemaInfo.IsNil)
            Console.WriteLine("SchemaInfo.SchemaElement: {0}", priceNode.SchemaInfo.SchemaElement)
            Console.WriteLine("SchemaInfo.SchemaType: {0}", priceNode.SchemaInfo.SchemaType)
            Console.WriteLine("SchemaInfo.Validity: {0}", priceNode.SchemaInfo.Validity)

            priceNode.InnerXml = "A"

            Dim priceNodes As XmlNodeList = document.SelectNodes("/bk:bookstore/bk:book/bk:price", manager)
            Dim lastprice As XmlNode = priceNodes(priceNodes.Count - 1)

            lastprice.InnerXml = "B"

            ' Validate the XML document with the invalid changes.
            ' The invalid changes cause schema validation errors.
            document.Validate(AddressOf ValidationEventHandler)

            ' Correct the invalid change to the first price element.
            priceNode.InnerXml = "8.99"

            ' Validate only the first book element. The last book
            ' element is invalid, but not included in validation.
            Dim bookNode As XmlNode = document.SelectSingleNode("/bk:bookstore/bk:book", manager)
            document.Validate(AddressOf ValidationEventHandler, bookNode)

        Catch ex As XmlException
            Console.WriteLine("XmlDocumentValidationExample.XmlException: {0}", ex.Message)

        Catch ex As XmlSchemaValidationException
            Console.WriteLine("XmlDocumentValidationExample.XmlSchemaValidationException: {0}", ex.Message)

        Catch ex As Exception
            Console.WriteLine("XmlDocumentValidationExample.Exception: {0}", ex.Message)

        End Try

    End Sub

    Shared Sub ValidationEventHandler(ByVal sender As Object, ByVal args As ValidationEventArgs)

        If args.Severity = XmlSeverityType.Warning Then
            Console.Write(vbCrLf & "WARNING: ")
        Else
            If args.Severity = XmlSeverityType.Error Then
                Console.Write(vbCrLf & "ERROR: ")
            End If
        End If
        Console.WriteLine(args.Message)

    End Sub

End Class

En el ejemplo se toma como entrada el archivo contosoBooks.xml.

<?xml version="1.0" encoding="utf-8" ?>
<bookstore xmlns="http://www.contoso.com/books">
    <book genre="autobiography" publicationdate="1981-03-22" ISBN="1-861003-11-0">
        <title>The Autobiography of Benjamin Franklin</title>
        <author>
            <first-name>Benjamin</first-name>
            <last-name>Franklin</last-name>
        </author>
        <price>8.99</price>
    </book>
    <book genre="novel" publicationdate="1967-11-17" ISBN="0-201-63361-2">
        <title>The Confidence Man</title>
        <author>
            <first-name>Herman</first-name>
            <last-name>Melville</last-name>
        </author>
        <price>11.99</price>
    </book>
    <book genre="philosophy" publicationdate="1991-02-15" ISBN="1-861001-57-6">
        <title>The Gorgias</title>
        <author>
            <name>Plato</name>
        </author>
        <price>9.99</price>
    </book>
</bookstore>

En el ejemplo también se toma como entrada el archivo contosoBooks.xsd.

<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://www.contoso.com/books" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:element name="bookstore">
        <xs:complexType>
            <xs:sequence>
                <xs:element maxOccurs="unbounded" name="book">
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element name="title" type="xs:string" />
                            <xs:element name="author">
                                <xs:complexType>
                                    <xs:sequence>
                                        <xs:element minOccurs="0" name="name" type="xs:string" />
                                        <xs:element minOccurs="0" name="first-name" type="xs:string" />
                                        <xs:element minOccurs="0" name="last-name" type="xs:string" />
                                    </xs:sequence>
                                </xs:complexType>
                            </xs:element>
                            <xs:element name="price" type="xs:decimal" />
                        </xs:sequence>
                        <xs:attribute name="genre" type="xs:string" use="required" />
                        <xs:attribute name="publicationdate" type="xs:date" use="required" />
                        <xs:attribute name="ISBN" type="xs:string" use="required" />
                    </xs:complexType>
                </xs:element>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
</xs:schema>

Tenga en cuenta lo siguiente a la hora de validar datos XML a medida que se cargan en el DOM.

  • En el ejemplo anterior, se llama a ValidationEventHandler cada vez que se encuentra un tipo no válido. Si no se establece un ValidationEventHandler en el XmlReader de validación, se produce una excepción XmlSchemaValidationException cuando se llama a Load si algún atributo o tipo de elemento no se corresponde con el tipo especificado en el esquema de validación.

  • Cuando se carga un documento XML en un objeto XmlDocument con un esquema asociado que define valores predeterminados, XmlDocument trata estos valores predeterminados como si aparecieran en el documento XML. Esto significa que la propiedad IsEmptyElement siempre devuelve false para un elemento que tenga los valores predeterminados del esquema. Aunque estuviera en el documento XML, se escribiría como un elemento vacío.

Validación de un documento XML en el DOM

El método Validate de la clase XmlDocument valida los datos XML que se cargan en el DOM con los esquemas de la propiedad XmlDocument del objeto Schemas. Después de realizar la validación correctamente, se aplican los valores predeterminados del esquema, los valores de texto se convierten en valores atómicos como sea preciso y la información de tipos se asocia a los elementos de información validados. Como resultado, los datos XML con tipo reemplazan a los datos XML sin tipo anteriores.

El siguiente ejemplo es similar al ejemplo de la sección anterior "Validación de un documento XML a medida que se carga en el DOM". En este ejemplo, el documento XML no se valida a medida que se carga en el DOM, sino después de cargarlo en el DOM utilizando el método Validate de la clase XmlDocument. El método Validate valida el documento XML con los esquemas XML contenidos en la propiedad Schemas de XmlDocument. Luego, se realizan modificaciones no válidas en el documento XML y dicho documento se vuelve a validar, lo que produce errores de validación del esquema. Por último, se corrige uno de los errores y, a continuación, se valida parcialmente parte del documento XML.

using System;
using System.Xml;
using System.Xml.Schema;

class XmlDocumentValidationExample
{
    static void Main(string[] args)
    {
        try
        {
            // Create a new XmlDocument instance and load
            // the XML document into the DOM.
            XmlDocument document = new XmlDocument();
            document.Load("contosoBooks.xml");

            // Add the XML schema for the XML document to the
            // Schemas property of the XmlDocument.
            document.Schemas.Add("http://www.contoso.com/books", "contosoBooks.xsd");

            // Validate the XML document loaded into the DOM.
            document.Validate(ValidationEventHandler);

            // Make an invalid change to the first and last
            // price elements in the XML document, and write
            // the XmlSchemaInfo values assigned to the price
            // element during validation to the console.
            XmlNamespaceManager manager = new XmlNamespaceManager(document.NameTable);
            manager.AddNamespace("bk", "http://www.contoso.com/books");

            XmlNode priceNode = document.SelectSingleNode(@"/bk:bookstore/bk:book/bk:price", manager);

            Console.WriteLine("SchemaInfo.IsDefault: {0}", priceNode.SchemaInfo.IsDefault);
            Console.WriteLine("SchemaInfo.IsNil: {0}", priceNode.SchemaInfo.IsNil);
            Console.WriteLine("SchemaInfo.SchemaElement: {0}", priceNode.SchemaInfo.SchemaElement);
            Console.WriteLine("SchemaInfo.SchemaType: {0}", priceNode.SchemaInfo.SchemaType);
            Console.WriteLine("SchemaInfo.Validity: {0}", priceNode.SchemaInfo.Validity);

            priceNode.InnerXml = "A";

            XmlNodeList priceNodes = document.SelectNodes(@"/bk:bookstore/bk:book/bk:price", manager);
            XmlNode lastprice = priceNodes[priceNodes.Count - 1];

            lastprice.InnerXml = "B";

            // Validate the XML document with the invalid changes.
            // The invalid changes cause schema validation errors.
            document.Validate(ValidationEventHandler);

            // Correct the invalid change to the first price element.
            priceNode.InnerXml = "8.99";

            // Validate only the first book element. The last book
            // element is invalid, but not included in validation.
            XmlNode bookNode = document.SelectSingleNode(@"/bk:bookstore/bk:book", manager);
            document.Validate(ValidationEventHandler, bookNode);
        }
        catch (XmlException ex)
        {
            Console.WriteLine("XmlDocumentValidationExample.XmlException: {0}", ex.Message);
        }
        catch(XmlSchemaValidationException ex)
        {
            Console.WriteLine("XmlDocumentValidationExample.XmlSchemaValidationException: {0}", ex.Message);
        }
        catch (Exception ex)
        {
            Console.WriteLine("XmlDocumentValidationExample.Exception: {0}", ex.Message);
        }
    }

    static void ValidationEventHandler(object sender, System.Xml.Schema.ValidationEventArgs args)
    {
        if (args.Severity == XmlSeverityType.Warning)
            Console.Write("\nWARNING: ");
        else if (args.Severity == XmlSeverityType.Error)
            Console.Write("\nERROR: ");

        Console.WriteLine(args.Message);
    }
}
Imports System.Xml
Imports System.Xml.Schema

Class XmlDocumentValidationExample

    Shared Sub Main()

        Try

            ' Create a new XmlDocument instance and load
            ' the XML document into the DOM.
            Dim document As XmlDocument = New XmlDocument()
            document.Load("contosoBooks.xml")

            ' Add the XML schema for the XML document to the
            ' Schemas property of the XmlDocument.
            document.Schemas.Add("http://www.contoso.com/books", "contosoBooks.xsd")

            ' Validate the XML document loaded into the DOM.
            document.Validate(AddressOf ValidationEventHandler)

            ' Make an invalid change to the first and last 
            ' price elements in the XML document, and write
            ' the XmlSchemaInfo values assigned to the price
            ' element during validation to the console.
            Dim manager As XmlNamespaceManager = New XmlNamespaceManager(document.NameTable)
            manager.AddNamespace("bk", "http://www.contoso.com/books")

            Dim priceNode As XmlNode = document.SelectSingleNode("/bk:bookstore/bk:book/bk:price", manager)

            Console.WriteLine("SchemaInfo.IsDefault: {0}", priceNode.SchemaInfo.IsDefault)
            Console.WriteLine("SchemaInfo.IsNil: {0}", priceNode.SchemaInfo.IsNil)
            Console.WriteLine("SchemaInfo.SchemaElement: {0}", priceNode.SchemaInfo.SchemaElement)
            Console.WriteLine("SchemaInfo.SchemaType: {0}", priceNode.SchemaInfo.SchemaType)
            Console.WriteLine("SchemaInfo.Validity: {0}", priceNode.SchemaInfo.Validity)

            priceNode.InnerXml = "A"

            Dim priceNodes As XmlNodeList = document.SelectNodes("/bk:bookstore/bk:book/bk:price", manager)
            Dim lastprice As XmlNode = priceNodes(priceNodes.Count - 1)

            lastprice.InnerXml = "B"

            ' Validate the XML document with the invalid changes.
            ' The invalid changes cause schema validation errors.
            document.Validate(AddressOf ValidationEventHandler)

            ' Correct the invalid change to the first price element.
            priceNode.InnerXml = "8.99"

            ' Validate only the first book element. The last book
            ' element is invalid, but not included in validation.
            Dim bookNode As XmlNode = document.SelectSingleNode("/bk:bookstore/bk:book", manager)
            document.Validate(AddressOf ValidationEventHandler, bookNode)

        Catch ex As XmlException
            Console.WriteLine("XmlDocumentValidationExample.XmlException: {0}", ex.Message)

        Catch ex As XmlSchemaValidationException
            Console.WriteLine("XmlDocumentValidationExample.XmlSchemaValidationException: {0}", ex.Message)

        Catch ex As Exception
            Console.WriteLine("XmlDocumentValidationExample.Exception: {0}", ex.Message)

        End Try

    End Sub

    Shared Sub ValidationEventHandler(ByVal sender As Object, ByVal args As ValidationEventArgs)

        If args.Severity = XmlSeverityType.Warning Then
            Console.Write(vbCrLf & "WARNING: ")
        Else
            If args.Severity = XmlSeverityType.Error Then
                Console.Write(vbCrLf & "ERROR: ")
            End If
        End If
        Console.WriteLine(args.Message)

    End Sub

End Class

En el ejemplo se toman como entrada los archivos contosoBooks.xml y contosoBooks.xsd que se mencionan en la sección anterior "Validación de un documento XML a medida que se carga en el DOM".

Control de advertencias y errores de validación

Los errores de validación de esquemas XML se presentan durante la validación de datos XML cargados en el DOM. Todos los errores de validación de esquemas se le notifican mientras se validan los datos a medida que se cargan o cuando se valida un documento XML que no estuviera previamente validado.

ValidationEventHandler controla los errores de validación. Si se ha asignado un ValidationEventHandler a la instancia de XmlReaderSettings o se ha pasado al método Validate de la clase XmlDocument, el ValidationEventHandler controlará los errores de validación de esquemas; de lo contrario, se inicia una XmlSchemaValidationException cuando se encuentra un error de validación de esquema.

Nota

Los datos XML se cargan en el DOM a pesar de los errores de validación de esquemas, a menos que ValidationEventHandler inicie una excepción para detener el proceso.

No se notifican advertencias de validación de esquemas a menos que se especifique la marca ReportValidationWarnings para el objeto XmlReaderSettings.

Para ver ejemplos sobre ValidationEventHandler, vea las secciones "Validación de un documento XML a medida que se carga en el DOM" y "Validación de un documento XML en el DOM".

Vea también