Convalida di un documento XML nel DOM

La classe XmlDocument non esegue la convalida del codice XML nel DOM (Document Object Model) in base a uno schema XSD (XML Schema Definition Language) o a una DTD (Document Type Definition) per impostazione predefinita. Viene solo verificato che il codice XML sia ben formato.

Per eseguire la convalida del codice XML nel modello DOM, è possibile convalidare il codice XML durante il caricamento nel DOM passando una convalida dello schema XmlReader al metodo Load della classe XmlDocument oppure convalidare un documento XML non convalidato in precedenza nel DOM usando il metodo Validate della classe XmlDocument.

Convalida di un documento XML durante il caricamento nel DOM

La classe XmlDocument convalida i dati XML durante il caricamento nel DOM quando un XmlReader di convalida viene passato al metodo Load della classe XmlDocument.

Una volta eseguita la convalida, vengono applicati i valori predefiniti dello schema, i valori di testo vengono convertiti in valori di tipo atomic in base alle necessità e le informazioni sui tipi vengono associate agli elementi delle informazioni convalidate. Di conseguenza, i dati XML tipizzati sostituiscono i dati XML in precedenza non tipizzati.

Creazione di un XmlReader di convalida di XML Schema

Per creare un tipo XmlReader di convalida di XML Schema, attenersi alla seguente procedura.

  1. Creare una nuova istanza di XmlReaderSettings.

  2. Aggiungere un XML Schema alla proprietà Schemas dell'istanza di XmlReaderSettings.

  3. Specificare Schema come proprietà ValidationType.

  4. È possibile eventualmente specificare la proprietà ValidationFlags e un evento ValidationEventHandler per gestire gli errori di convalida degli schemi e gli avvisi rilevati durante la convalida.

  5. Infine, passare l'oggetto XmlReaderSettings al metodo Create della classe XmlReader insieme al documento XML, creando un tipo XmlReader di convalida dello schema.

Esempio

Nell'esempio di codice seguente un tipo XmlReader di convalida dello schema esegue la convalida dei dati XML caricati nel DOM. Vengono apportate modifiche non valide al documento XML che viene quindi nuovamente convalidato, determinando errori di convalida dello schema. Infine, uno degli errori viene corretto e quindi una parte del documento XML viene parzialmente convalidata.

#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

Nell'esempio il file contosoBooks.xml viene considerato come input.

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

Nell'esempio il file contosoBooks.xsd viene considerato come input.

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

Quando si convalidano i dati XML durante il caricamento nel DOM, è necessario prendere in considerazione quanto segue.

  • Nell'esempio precedente, viene chiamato l'oggetto ValidationEventHandler ogni volta che viene rilevato un tipo non valido. Se non è impostato un oggetto ValidationEventHandler sull'oggetto XmlReader di convalida, quando viene chiamato XmlSchemaValidationException viene generata un'eccezione Load se un tipo di attributo o di elemento non corrisponde al tipo specificato nello schema di convalida.

  • Quando un documento XML viene caricato in un oggetto XmlDocument con uno schema associato che definisce valori predefiniti, l'oggetto XmlDocument tratta tali valori predefiniti come se si trovassero nel documento XML. Pertanto la proprietà IsEmptyElement restituisce sempre un valore false per un elemento ottenuto automaticamente dallo schema. Anche se è incluso nel documento XML, è stato scritto come elemento vuoto.

Convalida di un documento XML nel DOM

Il metodo Validate della classe XmlDocument esegue la convalida dei dati XML caricati nel DOM in base agli schemi nella proprietà XmlDocument dell'oggetto Schemas. Una volta eseguita la convalida, vengono applicati i valori predefiniti dello schema, i valori di testo vengono convertiti in valori di tipo atomic in base alle necessità e le informazioni sui tipi vengono associate agli elementi delle informazioni convalidate. Di conseguenza, i dati XML tipizzati sostituiscono i dati XML in precedenza non tipizzati.

L'esempio seguente è simile a quello riportato sopra in "Convalida di un documento XML durante il caricamento nel DOM". In questo esempio, il documento XML non viene convalidato durante il caricamento nel DOM, bensì dopo che è stato caricato nel DOM usando il metodo Validate della classe XmlDocument. Il metodo Validate esegue la convalida del documento XML in base agli schemi XML contenuti nella proprietà Schemas del XmlDocument. Vengono apportate modifiche non valide al documento XML che viene quindi riconvalidato, determinando errori di convalida dello schema. Infine, uno degli errori viene corretto e quindi una parte del documento XML viene parzialmente convalidata.

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

Nell'esempio vengono accettati come input i file contosoBooks.xml e contosoBooks.xsd a cui si fa riferimento in "Convalida di un documento XML durante il caricamento nel DOM".

Gestione degli errori di convalida e degli avvisi

Gli errori di convalida di XML Schema vengono segnalati durante la convalida dei dati XML caricati nel DOM. Viene inviata una notifica per tutti gli errori di convalida dello schema rilevati durante la convalida dei dati XML in fase di caricamento o durante la convalida di un documento XML non convalidato in precedenza.

Gli errori di convalida sono gestiti dal tipo ValidationEventHandler. Se un tipo ValidationEventHandler è stato assegnato all'istanza di XmlReaderSettings o passato al metodoValidate della classe XmlDocument, il ValidationEventHandler gestirà gli errori di convalida degli schemi. In caso contrario, viene generata un'eccezione XmlSchemaValidationException quando viene rilevato un errore di convalida.

Nota

I dati XML vengono caricati nel DOM indipendentemente dagli errori di convalida dello schema, a meno che il tipo ValidationEventHandler non generi un'eccezione che interrompe il processo.

Non vengono segnalati avvisi di convalida dello schema, a meno che non sia stato specificato il flag ReportValidationWarnings nell'oggetto XmlReaderSettings.

Per gli esempi che illustrano il tipo ValidationEventHandler, vedere "Convalida di un documento XML durante il caricamento nel DOM" e "Convalida di un documento XML nel DOM" riportati in precedenza.

Vedi anche