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.