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()

Su richiesta di un amico pubblico la classe "valda" in C# (per la traduzion vb.net ci si appoggi ad uno dei convertitori disponibili in rete).

using System;

using System.Collections.Generic;

using System.Text;

using System.Xml;

using System.Xml.Schema;

 

namespace ValidaXml

{

    class Valida

    {

        // definizione lista

        private static List<Elementi> listValidate = null;

 

        // costruttore privato perchè tutti i membri sono statici

        private Valida()

        {

        }

 

        /// <summary>

        /// Validazione del file xml

        ///

        /// </summary>

        /// <param name="xmlFile"></param>

        /// <param name="xsdFile"></param>

        /// <returns></returns>

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

        {

            listValidate = new List<Elementi>();

            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);

            try

            {

                while (txtReader.Read())

                {

                    switch (txtReader.NodeType)

                    {

                        case XmlNodeType.Element:

                        {

                            int k = txtReader.Depth;

                            string[] s = new string[] { string.Empty, string.Empty, string.Empty, string.Empty, string.Empty };

                            s[0] = txtReader.Name;

                            s[1] = "Elemento";

                            s[2] = k.ToString();

                            s[4] = txtReader.Value;

                            listValidate.Add(new Elementi(s));

                            s[1] = "Attributo";

                            k += 1;

                            s[2] = k.ToString();

                            if (txtReader.HasAttributes)

                            {

                               

                                 while (txtReader.MoveToNextAttribute())

                                {

                                    s[0] = txtReader.Name;

                                    s[4] = txtReader.Value;

                                    listValidate.Add(new Elementi(s));

                                }

                            }

                            break;

                        }

                        case XmlNodeType.Text:

                        {

                            break;

                        }

 

                    }

                }

                txtReader.Close();

            }

            catch (XmlSchemaValidationException ex)

            {

                listValidate.Add(new Elementi(new string[] { ex.Source, "XmlSchemaValidationException", ex.LineNumber.ToString(), ex.Message,string.Empty }));

            }

            catch (XmlSchemaInferenceException ex)

            {

                listValidate.Add(new Elementi(new string[] { ex.Source, "XmlSchemaInferenceException", ex.LineNumber.ToString(), ex.Message, string.Empty }));

            }

            catch (XmlSchemaException ex)

            {

                listValidate.Add(new Elementi(new string[] { ex.Source, "XmlSchemaException", ex.LineNumber.ToString(), ex.Message, string.Empty }));

            }

            catch (XmlException ex)

            {

                listValidate.Add(new Elementi(new string[] { ex.Source, "XmlException", ex.LineNumber.ToString(), ex.Message, string.Empty }));

            }

            catch (Exception ex)

            {

                listValidate.Add(new Elementi(new string[] { string.Empty, "Exception", "", ex.Message, string.Empty }));

            }

            return listValidate;

        }

 

        static void settings_ValidationEventHandler(object sender, ValidationEventArgs e)

        {

            listValidate.Add(new Elementi(new string[] { string.Empty, e.Severity.ToString(), "", e.Message, string.Empty }));

        }

    }

 

}

 

 

Print | posted on mercoledì 2 dicembre 2009 18:19

Feedback

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

Left by Giacomo at 17/07/2008 17:59
Gravatar ciao!
potresti postare tutto il codice della validazione?

Thank you in advance!
Giacomo.

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

Left by xcxc at 25/11/2008 13:07
Gravatar ok

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

Left by Silvano at 25/06/2009 13:17
Gravatar grazie

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

Left by silvano at 25/06/2009 13:18
Gravatar grazie

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

Left by Silvano at 25/06/2009 13:19
Gravatar grazie

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

Left by vibstudio at 02/12/2009 17:54
Gravatar Ciao Luciano, com'è possibile visionare la classe Validate? Non sono iscritto al tuo blog e, nonstante sarei molto interessato, non so come fare. Non mi pare sia possibile registrarsi.

Grazie anticipatamente.
vibstudio

Your comment:





 
Please add 2 and 7 and type the answer here:

Copyright © Luciano Bastianello

Design by Bartosz Brzezinski

Design by Phil Haack Based On A Design By Bartosz Brzezinski