CodeGym /Corsi /C# SELF /Validazione XML con...

Validazione XML con XSD-schema

C# SELF
Livello 48, Lezione 4
Disponibile

1. A cosa serve la validazione XML

XML è un formato molto flessibile, a volte anche troppo. A differenza di dati fortemente tipizzati, XML "tollera" errori, e se dimentichi di chiudere un tag, o qualcuno mette il nome sbagliato di un attributo, il programma può dare un errore durante il parsing… o non accorgersi del problema, il che è peggio.

La validazione tramite XSD (XML Schema Definition) è un modo per assicurarsi che il tuo file XML rispetti un contratto predefinito: come si chiamano i tag, in che ordine vanno, di che tipo sono, se sono obbligatori e quante occorrenze sono ammesse. È come il controllo passaporti per i tuoi dati — lo schema dice: "Non si entra senza il campo richiesto o se il campo non ha la lunghezza giusta!"

La validazione è importante nei sistemi enterprise, nello scambio di dati tra sistemi diversi, negli API — ovunque sia indesiderato accettare "silenziosamente" strutture malformate.

XSD (XML Schema Definition) è un documento XML separato che formalizza la struttura di un altro XML. Nell'XSD descrivi: quali tag sono ammessi, quali sono obbligatori, i tipi di attributi o di elementi figli, pattern per le stringhe, vincoli per i numeri, persino i valori possibili (via restrizioni e enumerazioni).

XML XSD (descrizione della struttura)
<person age="23">Ivan</person>
<element name="person" ... />
<item price="1000"/>
<element name="item" type="..." />

XSD è concettualmente simile a JSON Schema nel mondo JSON.

2. Esempio di XSD e XML correlato

Esempio XML

<person age="23">
  <name>Ivan</name>
  <email>ivan@example.com</email>
</person>

Esempio XSD

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
   <xs:element name="person">
     <xs:complexType>
       <xs:sequence>
         <xs:element name="name" type="xs:string"/>
         <xs:element name="email" type="xs:string" minOccurs="0"/>
       </xs:sequence>
       <xs:attribute name="age" type="xs:positiveInteger" use="required"/>
     </xs:complexType>
   </xs:element>
</xs:schema>

Che cosa descrive questo schema:

  • L'elemento root è <person>.
  • Dentro <person> devono esserci gli elementi <name> (obbligatorio) e <email> (opzionale).
  • Il <person> deve avere l'attributo age con un valore intero positivo.

3. Validare XML con XSD in .NET

In .NET il classico è usare gli namespace System.Xml e System.Xml.Schema.

Flusso di lavoro:

  1. Caricare il file XML
  2. Caricare lo schema XSD
  3. "Attaccare" lo schema alla validazione dell'XML
  4. Avviare il processo di validazione e gestire eventuali errori

Ecco un esempio base:

using System;
using System.IO;
using System.Xml;
using System.Xml.Schema;

// 1. Handler per gli errori di validazione
void ValidationCallBack(object? sender, ValidationEventArgs e)
{
    Console.WriteLine($"Errore di validazione: {e.Message}");
}

string xmlPath = "person.xml";
string xsdPath = "person.xsd";

// 2. Carichiamo lo schema
XmlSchemaSet schemas = new XmlSchemaSet();
schemas.Add("", xsdPath);

XmlReaderSettings settings = new XmlReaderSettings();
settings.Schemas = schemas;
settings.ValidationType = ValidationType.Schema;
settings.ValidationEventHandler += ValidationCallBack;

// 3. Apriamo l'XML con le impostazioni
using XmlReader reader = XmlReader.Create(xmlPath, settings);
while (reader.Read())
{
    // Semplicemente scorriamo il documento - la validazione avviene "on the fly"
}

Console.WriteLine("Validazione completata!");

Note:

  • Tutti gli errori di validazione saranno intercettati nel callback ValidationCallBack.
  • Se non ci sono errori — il documento rispetta lo schema (ValidationType.Schema).
  • Se ci sono discrepanze (manca age, email non valida, campo extra ecc.) — compariranno nella console.

Tipi diversi di errori e feedback

La validazione tramite XSD può "lamentarsi" per vari motivi. Ecco gli scenari più comuni e esempi di errori:

  • Manca un elemento obbligatorio (di default minOccurs="1")
  • Tag extra non descritto nello XSD
  • Attributo di tipo sbagliato (age="abc" invece di un numero)
  • Stringhe che non rispettano il pattern (definito con <xs:pattern>)

Errore tipico:

Errore di validazione: L'elemento 'age' con contenuto testuale 'abc' non è valido. Era atteso un valore di tipo 'xs:positiveInteger'.

4. XSD più complicati: tipi, enumerazioni, pattern

XSD è praticamente un linguaggio per descrivere dati validi. Ecco alcuni esempi avanzati:

Enumerazione di valori ammessi

<xs:element name="gender">
  <xs:simpleType>
    <xs:restriction base="xs:string">
      <xs:enumeration value="male"/>
      <xs:enumeration value="female"/>
      <xs:enumeration value="diverse"/>
    </xs:restriction>
  </xs:simpleType>
</xs:element>

Limitazione della lunghezza della stringa

<xs:element name="code">
  <xs:simpleType>
    <xs:restriction base="xs:string">
      <xs:length value="8"/>
    </xs:restriction>
  </xs:simpleType>
</xs:element>

Pattern per email (semplificato)

<xs:element name="email">
  <xs:simpleType>
    <xs:restriction base="xs:string">
      <xs:pattern value="\w+@\w+\.\w+"/>
    </xs:restriction>
  </xs:simpleType>
</xs:element>

Puoi creare tipi personalizzati, ereditarli, usare elementi annidati — praticamente come in OOP!

5. Validazione di un documento complesso

Immaginiamo che la nostra app didattica ora esporti una lista di studenti in XML. Aggiungiamo del codice!

Esempio XML

<students>
  <student id="1">
    <name>Elena</name>
    <grade>5</grade>
  </student>
  <student id="2">
    <name>Alexey</name>
    <grade>4</grade>
  </student>
</students>

Schema XSD

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="students">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="student" maxOccurs="unbounded">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="name" type="xs:string"/>
              <xs:element name="grade">
                <xs:simpleType>
                  <xs:restriction base="xs:integer">
                    <xs:minInclusive value="1"/>
                    <xs:maxInclusive value="5"/>
                  </xs:restriction>
                </xs:simpleType>
              </xs:element>
            </xs:sequence>
            <xs:attribute name="id" type="xs:integer" use="required"/>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

Validazione nel codice (stessi approcci):

// Percorsi ai file
string xmlPath = "students.xml";
string xsdPath = "students.xsd";

XmlSchemaSet schemas = new XmlSchemaSet();
schemas.Add("", xsdPath);

XmlReaderSettings settings = new XmlReaderSettings();
settings.Schemas = schemas;
settings.ValidationType = ValidationType.Schema;
settings.ValidationEventHandler += ValidationCallBack;

using XmlReader reader = XmlReader.Create(xmlPath, settings);
while (reader.Read()) { /* tutto come prima */ }

6. Sfumature utili

Come specificare lo schema direttamente nell'XML (xsi:schemaLocation)

In pratica si trovano spesso file XML che dichiarano nell'elemento root gli attributi xsi:schemaLocation o xsi:noNamespaceSchemaLocation:

<students xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:noNamespaceSchemaLocation="students.xsd">
    ...
</students>

Questo non valida automaticamente il file, ma aiuta alcuni validator ed editor a trovare lo schema per il controllo. Nella validazione .NET non è obbligatorio, ma è formalmente corretto.

Validazione "on the fly" e in memoria — con XDocument

Se lavori con LINQ to XML (XDocument), puoi anche validare il documento XML in memoria, senza usare file:

using System.Xml.Linq;
using System.Xml.Schema;

// Caricamento dello schema
XmlSchemaSet schema = new XmlSchemaSet();
schema.Add("", "students.xsd");

// Caricamento dell'XML in memoria
XDocument doc = XDocument.Load("students.xml");

// Validazione
doc.Validate(schema,
    (o, e) => Console.WriteLine($"Errore: {e.Message}"),
    true // Controllare i warning (spesso ridondante)
);

Questo approccio è comodo se crei o modifichi XML programmaticamente e vuoi assicurarti di non generare un altro mostro XML che violi lo schema.

7. Errori tipici nella validazione XML con XSD

Errore n.1: hai dimenticato di aggiungere lo schema o il percorso allo XSD è sbagliato.
Di conseguenza non viene eseguita alcuna validazione e il file XML passa "attraverso la guardia", anche se contiene errori. Spesso il percorso è relativo e l'app cerca il file in una cartella inaspettata. Per i test è meglio usare un percorso assoluto o mettere lo schema accanto all'eseguibile.

Errore n.2: gli namespace non coincidono.
Se lo schema usa uno namespace, devi passarne il valore come primo argomento quando aggiungi lo schema a XmlSchemaSet.Add. Altrimenti la validazione fallirà anche se la struttura XML è corretta. Se non ci sono namespace — passa una stringa vuota.

Errore n.3: ordine degli elementi non corrispondente.
Se nello schema è definito un <xs:sequence>, allora l'ordine degli elementi conta. Un XML con gli elementi giusti ma in ordine sbagliato sarà considerato invalido.

Errore n.4: nell'XML sono indicati più namespace.
Se il documento usa più di uno namespace, questo può causare comportamenti inaspettati nella validazione. Supportare namespace multipli richiede attenzione e configurazione precisa degli schema.

Errore n.5: non raccogliere e non salvare gli errori.
Stampare gli errori in console può andare bene per il debug, ma non per un'app in produzione. È meglio raccogliere gli errori in una lista e presentarli all'utente in modo fruibile — soprattutto quando si validano molti file (ad esempio su un web server).

2
Compito
C# SELF, livello 48, lezione 4
Bloccato
Estensione della struttura XML e validazione con molte regole
Estensione della struttura XML e validazione con molte regole
1
Sondaggio/quiz
Lavorare con dati XML, livello 48, lezione 4
Non disponibile
Lavorare con dati XML
Configurazione della serializzazione XML
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION