Convalida dello schema con XPathNavigator

La classe XmlDocument consente di convalidare il contenuto XML di un oggetto XmlDocument in due modi diversi. Il primo modo prevede la convalida del contenuto XML mediante un oggetto di convalida XmlReader, mentre il secondo modo prevede l'uso del metodo Validate della classe XmlDocument. È inoltre possibile eseguire la convalida di sola lettura del contenuto XML usando la classe XPathDocument.

Convalida di dati XML

Per impostazione predefinita, la classe XmlDocument non consente di convalidare un documento XML mediante la DTD (Document Type Definition) o lo schema XSD (XML Schema Definition Language). Tale classe consente soltanto di verificare che il documento XML sia in formato corretto.

Nel primo modo, il documento XML viene convalidato durante il caricamento in un oggetto XmlDocument usando un oggetto di convalida XmlReader. Nel secondo modo, il documento XML non tipizzato in precedenza viene convalidato usando il metodo Validate della classe XmlDocument. In entrambi i casi, le modifiche apportate al documento XML convalidato possono essere convalidate di nuovo usando il metodo Validate della classe XmlDocument.

Convalida di un documento durante il caricamento

Un oggetto di convalida XmlReader viene creato passando un oggetto XmlReaderSettings al metodo Create della classe XmlReader che accetta un oggetto XmlReaderSettings come parametro. Nell'oggetto XmlReaderSettings passato come parametro è presente una proprietà ValidationType impostata su Schema e un XML Schema per il documento XML contenuto nell'oggetto XmlDocument aggiunto alla relativa proprietà Schemas. L'oggetto di convalida XmlReader viene quindi usato per creare l'oggetto XmlDocument.

Nell'esempio seguente viene convalidato il contosoBooks.xml file durante il caricamento nel XmlDocument creando il XmlDocument utilizzando un oggetto di convalida dell'oggetto XmlReader oggetto. Dal momento che il documento XML è valido in base al relativo schema, non verrà generato alcun errore o avviso di convalida dello schema.

Imports System  
Imports System.Xml  
Imports System.Xml.Schema  
Imports System.Xml.XPath  
  
Class ValidatingReaderExample  
  
    Shared Sub Main(ByVal args() As String)  
  
        Try  
            Dim settings As XmlReaderSettings = New XmlReaderSettings()  
            settings.Schemas.Add("http://www.contoso.com/books", "contosoBooks.xsd")  
            settings.ValidationType = ValidationType.Schema  
  
            Dim reader As XmlReader = XmlReader.Create("contosoBooks.xml", settings)  
  
            Dim document As XmlDocument = New XmlDocument()  
            document.Load(reader)  
            Dim navigator As XPathNavigator = document.CreateNavigator()  
  
        Catch e As Exception  
            Console.WriteLine("ValidatingReaderExample.Exception: {0}", e.Message)  
        End Try  
  
    End Sub  
  
    Shared Sub SchemaValidationHandler(ByVal sender As Object, ByVal e As ValidationEventArgs)  
  
        Select Case e.Severity  
            Case XmlSeverityType.Error  
                Console.WriteLine("Schema Validation Error: {0}", e.Message)  
                Exit Sub  
            Case XmlSeverityType.Warning  
                Console.WriteLine("Schema Validation Warning: {0}", e.Message)  
                Exit Sub  
        End Select  
  
    End Sub  
  
End Class  
using System;  
using System.Xml;  
using System.Xml.Schema;  
using System.Xml.XPath;  
  
class ValidatingReaderExample  
{  
    static void Main(string[] args)  
    {  
        try  
        {  
            XmlReaderSettings settings = new XmlReaderSettings();  
            settings.Schemas.Add("http://www.contoso.com/books", "contosoBooks.xsd");  
            settings.ValidationType = ValidationType.Schema;  
  
            XmlReader reader = XmlReader.Create("contosoBooks.xml", settings);  
  
            XmlDocument document = new XmlDocument();  
            document.Load(reader);  
            XPathNavigator navigator = document.CreateNavigator();  
        }  
        catch (Exception e)  
        {  
            Console.WriteLine("ValidatingReaderExample.Exception: {0}", e.Message);  
        }  
    }  
  
    static void SchemaValidationHandler(object sender, ValidationEventArgs e)  
    {  
        switch (e.Severity)  
        {  
            case XmlSeverityType.Error:  
                Console.WriteLine("Schema Validation Error: {0}", e.Message);  
                break;  
            case XmlSeverityType.Warning:  
                Console.WriteLine("Schema Validation Warning: {0}", e.Message);  
                break;  
        }  
    }  
}  

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>

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

Nell'esempio precedente verrà generata un'eccezione XmlSchemaValidationException quando si chiama Load se il tipo di qualsiasi attributo o elemento non corrisponde al tipo specificato nello schema di convalida. Se ValidationEventHandler è impostato sull'oggetto XmlReader di convalida, verrà chiamato ValidationEventHandler ogni volta in cui viene individuato un tipo non valido.

Verrà generata un'eccezione XmlSchemaException quando TypedValue accede a un attributo o un elemento la cui proprietà invalid è impostata su XPathNavigator.

È possibile usare la proprietà Validity per determinare se un singolo attributo o elemento è valido quando si accede ad attributi o elementi tramite XPathNavigator.

Nota

Quando un documento XML viene caricato in un oggetto XmlDocument a cui è associato uno schema che definisce dei valori predefiniti, questi vengono considerati dall'oggetto XmlDocument come se fossero contenuti nel documento XML. Ciò significa che la proprietà IsEmptyElement restituisce sempre false per un elemento che è stato modificato dallo schema, anche se nel documento XML era stato scritto come elemento vuoto.

Convalida di un documento con il metodo Validate

Il metodo Validate della classe XmlDocument consente di convalidare il documento XML contenuto in un oggetto XmlDocument in base agli schemi specificati nella proprietà XmlDocument dell'oggetto Schemas e di aumentare l'infoset. Il risultato è la sostituzione di un documento XML non tipizzato in precedenza nell'oggetto XmlDocument con un documento tipizzato.

Per segnalare gli errori e gli avvisi di convalida dello schema, nell'oggetto XmlDocument viene usato il delegato ValidationEventHandler passato come parametro al metodo Validate.

Nell'esempio seguente viene convalidato il file contosoBooks.xml contenuto nell'oggetto XmlDocument in base allo schema contosoBooks.xsd contenuto nella proprietà XmlDocument dell'oggetto Schemas.

Imports System  
Imports System.Xml  
Imports System.Xml.Schema  
Imports System.Xml.XPath  
  
Class ValidateExample  
  
    Shared Sub Main(ByVal args() As String)  
  
        Dim document As XmlDocument = New XmlDocument()  
        document.Load("contosoBooks.xml")  
        Dim navigator As XPathNavigator = document.CreateNavigator()  
  
        document.Schemas.Add("http://www.contoso.com/books", "contosoBooks.xsd")  
        Dim validation As ValidationEventHandler = New ValidationEventHandler(AddressOf SchemaValidationHandler)  
  
        document.Validate(validation)  
  
    End Sub  
  
    Shared Sub SchemaValidationHandler(ByVal sender As Object, ByVal e As ValidationEventArgs)  
  
        Select Case e.Severity  
            Case XmlSeverityType.Error  
                Console.WriteLine("Schema Validation Error: {0}", e.Message)  
                Exit Sub  
            Case XmlSeverityType.Warning  
                Console.WriteLine("Schema Validation Warning: {0}", e.Message)  
                Exit Sub  
        End Select  
  
    End Sub  
  
End Class  
using System;  
using System.Xml;  
using System.Xml.Schema;  
using System.Xml.XPath;  
  
class ValidateExample  
{  
    static void Main(string[] args)  
    {  
        XmlDocument document = new XmlDocument();  
        document.Load("contosoBooks.xml");  
        XPathNavigator navigator = document.CreateNavigator();  
  
        document.Schemas.Add("http://www.contoso.com/books", "contosoBooks.xsd");  
        ValidationEventHandler validation = new ValidationEventHandler(SchemaValidationHandler);  
  
        document.Validate(validation);  
    }  
  
    static void SchemaValidationHandler(object sender, ValidationEventArgs e)  
    {  
        switch (e.Severity)  
        {  
            case XmlSeverityType.Error:  
                Console.WriteLine("Schema Validation Error: {0}", e.Message);  
                break;  
            case XmlSeverityType.Warning:  
                Console.WriteLine("Schema Validation Warning: {0}", e.Message);  
                break;  
        }  
    }  
}  

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>

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

Convalida delle modifiche

Dopo aver apportato delle modifiche a un documento XML, è possibile convalidare le modifiche in base allo schema per il documento XML usando il metodo Validate della classe XmlDocument.

Nell'esempio seguente viene convalidato il contosoBooks.xml file durante il caricamento nel XmlDocument creando il XmlDocument utilizzando un oggetto di convalida dell'oggetto XmlReader oggetto. Il documento XML viene convalidato correttamente durante il caricamento e non viene generato alcun errore o avviso di convalida dello schema. Nell'esempio vengono quindi apportate due modifiche al documento XML che risultano non valide in base allo schema contosoBooks.xsd. Nella prima modifica viene inserito un elemento figlio non valido che genera un errore di convalida dello schema. Nella seconda modifica, invece, il valore di un nodo tipizzato viene impostato su un valore non valido in base al tipo del nodo e viene generata un'eccezione.

Imports System  
Imports System.Xml  
Imports System.Xml.Schema  
Imports System.Xml.XPath  
  
Class ValidatingReaderExample  
  
    Shared Sub Main(ByVal args() As String)  
  
        Try  
            Dim settings As XmlReaderSettings = New XmlReaderSettings()  
            settings.Schemas.Add("http://www.contoso.com/books", "contosoBooks.xsd")  
            settings.ValidationType = ValidationType.Schema  
  
            Dim reader As XmlReader = XmlReader.Create("contosoBooks.xml", settings)  
  
            Dim document As XmlDocument = New XmlDocument()  
            document.Load(reader)  
            Dim navigator As XPathNavigator = document.CreateNavigator()  
  
            Dim validation As ValidationEventHandler = New ValidationEventHandler(AddressOf SchemaValidationHandler)  
  
            navigator.MoveToChild("bookstore", "http://www.contoso.com/books")  
            navigator.MoveToChild("book", "http://www.contoso.com/books")  
            navigator.MoveToChild("author", "http://www.contoso.com/books")  
  
            navigator.AppendChild("<title>Book Title</title>")  
  
            document.Validate(validation)  
  
            navigator.MoveToParent()  
            navigator.MoveToChild("price", "http://www.contoso.com/books")  
            navigator.SetTypedValue(DateTime.Now)  
        Catch e As Exception  
            Console.WriteLine("ValidatingReaderExample.Exception: {0}", e.Message)  
        End Try  
  
    End Sub  
  
    Shared Sub SchemaValidationHandler(ByVal sender As Object, ByVal e As ValidationEventArgs)  
  
        Select Case e.Severity  
            Case XmlSeverityType.Error  
                Console.WriteLine("Schema Validation Error: {0}", e.Message)  
                Exit Sub  
            Case XmlSeverityType.Warning  
                Console.WriteLine("Schema Validation Warning: {0}", e.Message)  
                Exit Sub  
        End Select  
  
    End Sub  
  
End Class  
using System;  
using System.Xml;  
using System.Xml.Schema;  
using System.Xml.XPath;  
  
class ValidatingReaderExample  
{  
    static void Main(string[] args)  
    {  
        try  
        {  
            XmlReaderSettings settings = new XmlReaderSettings();  
            settings.Schemas.Add("http://www.contoso.com/books", "contosoBooks.xsd");  
            settings.ValidationType = ValidationType.Schema;  
  
            XmlReader reader = XmlReader.Create("contosoBooks.xml", settings);  
  
            XmlDocument document = new XmlDocument();  
            document.Load(reader);  
            XPathNavigator navigator = document.CreateNavigator();  
  
            ValidationEventHandler validation = new ValidationEventHandler(SchemaValidationHandler);  
  
            navigator.MoveToChild("bookstore", "http://www.contoso.com/books");  
            navigator.MoveToChild("book", "http://www.contoso.com/books");  
            navigator.MoveToChild("author", "http://www.contoso.com/books");  
  
            navigator.AppendChild("<title>Book Title</title>");  
  
            document.Validate(validation);  
  
            navigator.MoveToParent();  
            navigator.MoveToChild("price", "http://www.contoso.com/books");  
            navigator.SetTypedValue(DateTime.Now);  
        }  
        catch (Exception e)  
        {  
            Console.WriteLine("ValidatingReaderExample.Exception: {0}", e.Message);  
        }  
    }  
  
    static void SchemaValidationHandler(object sender, ValidationEventArgs e)  
    {  
        switch (e.Severity)  
        {  
            case XmlSeverityType.Error:  
                Console.WriteLine("Schema Validation Error: {0}", e.Message);  
                break;  
            case XmlSeverityType.Warning:  
                Console.WriteLine("Schema Validation Warning: {0}", e.Message);  
                break;  
        }  
    }  
}  

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>

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

Nell'esempio precedente, vengono apportate due modifiche al documento XML contenuto nell'oggetto XmlDocument. Durante il caricamento del documento XML, se fossero stati rilevati errori di convalida dello schema, sarebbero stati gestiti dal gestore eventi di convalida e darebbero stati scritti nella console.

In questo esempio, gli errori di convalida sono stati introdotti dopo il caricamento del documento XML e sono stati rilevati usando il metodo Validate della classe XmlDocument.

Le modifiche effettuate usando il metodo SetTypedValue della classe XPathNavigator hanno restituito un tipo InvalidCastException poiché il nuovo valore non era valido in base al tipo di schema del nodo.

Per altre informazioni sulla modifica dei valori mediante il metodo SetTypedValue, vedere l'argomento Modifica dei dati XML con XPathNavigator.

Convalida di sola lettura

La classe XPathDocument è una rappresentazione in memoria e di sola lettura di un documento XML. Le classi XPathDocument e XmlDocument consentono di creare oggetti XPathNavigator per esplorare e modificare i documenti XML. Dal momento che la classe XPathDocument è di sola lettura, gli oggetti XPathNavigator restituiti dagli oggetti XPathDocument non sono in grado di modificare il documento XML contenuto nell'oggetto XPathDocument.

In caso di convalida, è possibile creare un oggetto XPathDocument nello stesso modo in cui si crea un oggetto XmlDocument usando un oggetto di convalida XmlReader come descritto in precedenza in questo argomento. L'oggetto XPathDocument consente di convalidare il documento XML durante il caricamento; tuttavia, dal momento che non è possibile modificare i dati XML nell'oggetto XPathDocument, non sarà possibile eseguire di nuovo la convalida del documento XML.

Per altre informazioni sulla creazioni di oggetti XPathNavigator modificabili e in sola lettura, vedere l'argomento Lettura di dati XML con XPathDocument e XmlDocument.

Vedi anche