sabato 5 aprile 2008

Validazione di un file XML con un file XSD con C# e VB.NET

Dovendolo fare "per lavoro" mi sono messo alla ricerca di un semplice "validatore" di file .XML mediante un file .XSD.
Nella rete ho trovato programmi che con xml "vendevano" e facevano praticamente di tutto, dalla gestione dei documenti alla "semplice" programmazione, tutto fuorchè quello che interessava a me, la sola validazione di un file XML con un file XSD.

E cioè le operazioni: caricare unf ile .XML, caricare un file .XSD e .. mostrare gli errori! nulla di più.
Così ho deciso di scrivermelo.
Ho trovato, suggerito da un amico che non cito (poi si capirà) un link (non andateci che perdete solo del tempo): http://www.codeguru.com/Csharp/Csharp/cs_data/xml/article.php/c6737/
A questo link ho trovato sì quello che mi interessava, peccato che le classi e i metodi usati fossero stati nel frattempo dichiarati obsoleti.
Mi sono messo alla caccia quindi di altri esempi che usassero le nuove classi, nulla, tutti gli esempi che ho trovato usavano anch'essi gli stessi metodi dichiarati già obsoleti, e volete che io mi metta a copiare esempi già vecchi? manco morto!
Una piccola ricerca sul mio MSDN locale, quante volte ho invitato qualche amico a fare sempre la prima ricerca sul proprio help in linea e io ci sono cascato come una pera, chiedo scusa, si sa il calzolaio va in giro con le scarpe rotte, l'idraulico ha in casa sempre un tubo che perde, il programmatore che dovrebbe fare della pulizia e dell'essenziale una regola di vita si circonda sempre e ovunque di cose ed orpelli del tutto inutili tanto a ricordare che si è stupidi e si fa un lavoro previsto per il massimo della stupidità una macchina che non fa altro che fare ciò che gli è stato detto di fare :)

Pagato il tributo alla mia stupidità .. su MSDN ho trovato  XmlValidatingReader.SchemaType Property che ha aperto le porte alla comprensione e alla soluzione.

Ho cominciato con il definire una nuova classe "Valida" con un metodo principale per la restituzione di una lista degli elementi, degli attributi di ciascun elemento e .. degli errori riscontrati durante la validazione, a proposito si deve sapere che se il validatore incontra un errore qualsiasi il metodo finisce a quel punto.

C#
public static List<Elementi> Validate(string xmlFile, string xsdFile)

VB.NET (si noti, non lo dirò più quanto C# sia più essenziale e meno prolisso di VB.NET)

Public Shared Function Validate(ByVal xmlFile As String, ByVal xsdFile As String) As List(Of Elementi)

La funzione restituisce una lista di Elementi (Elementi è una classe generata per lo scopo, contiene i campi, tutti stringa, necessari all'interfacciamento con un dataset locale non tipizzato che ho utilizzato per mostrare su una datagridview i risultati), data la sintassi si tratta di una lista "tipizzata", l'oggetto infatti è predisposto per ricevere solo oggetti di tipo Elementi.
La classe tipizzata Elementi contiene i campi, ordine obbligatorio: Elemento, Tipo, Livello, Messaggio, Valore, l'ho dotata di un costruttore personalizzato che riceve come argomento un array con i valori dei campi.
La classe Elementi non serve alla nostra trattazione.

C#
XmlReaderSettings settings = new XmlReaderSettings();
settings.Schemas.Add(null,xsdFile);
settings.ValidationType = ValidationType.Schema;
XmlReader txtReader = XmlReader.Create(xmlFile, settings);            settings.ValidationEventHandler += new ValidationEventHandler(settings_ValidationEventHandler)

VB.NET
Dim settings As New XmlReaderSettings()
settings.Schemas.Add(Nothing, xsdFile)
settings.ValidationType = ValidationType.Schema
Dim txtReader As XmlReader = XmlReader.Create(xmlFile, settings)
AddHandler settings.ValidationEventHandler, AddressOf settings_ValidationEventHandler

Questo blocco di istruzioni definisce nell'ordine

  1. un oggetto di tipo XmlReaderSettings, necessario per impostare il file xsd contenente la struttura che "valida" il file xml
  2. Aggiunta dello schema xsd (riferimento al file di validazione)
  3. Definizione di un reader di tipo XmlReader con passaggio del file xml e della classe del validatore
  4. Abbonamento ad un evento e definizione del gestore dell'evento ValidationEventHandler

Finito questo passaggio per far "funzionare" il validatore è sufficiente eseguire il ciclo di lettura:

C#
while (txtReader.Read())

VB.NET
While txtReader.Read()

Nessun commento: