LINQ: da xml a classi C#

By | 2 novembre 2009

Proseguo la mia serie di articoli dedicati alla programmazione con C# e LINQ.

Nel mio precedente mio post ho presentato un semplice metodo per serializzare una classe C# con LINQ.

Oggi voglio descrivere l’altra faccia della medaglia: partendo da un file XML vedremo come sia possibile popolare le corrispondenti classi C#.

Partiamo dunque con il nostro esempio.

Supponiamo di avere un file xml che contiene l’elenco dei comuni italiani con il loro prefisso telefonico.

Vogliamo caricare questo file in una lista di oggetti C# con i quali sia più comodo lavorare all’interno della nostra applicazione.

Definiamo quindi il file Comuni.xml nel seguente modo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<comuni>
  <comune>
    <prefisso>045</prefisso>
    <descrizione>Verona</descrizione>
  </comune>
  <comune>
    <prefisso>02</prefisso>
    <descrizione>Milano</descrizione>
  </comune>
  <comune>
    <prefisso>06</prefisso>
    <descrizione>Roma</descrizione>
  </comune>
  <comune>
    <prefisso>011</prefisso>
    <descrizione>Torino</descrizione>
  </comune>
  <comune>
    <prefisso>055</prefisso>
    <descrizione>Firenze</descrizione>
  </comune>
...
</comuni>

Partendo da questo xml definiamo nel nostro progetto una classe Comune che andremo poi a popolare con i dati del singolo comune.

In caso di strutture XML più complesse si possono utilizzare dei tool di generazione di classi per ottenere le classi direttamente dall’xml, ma nel nostro caso definiamo la classe a mano vista la sua semplicità.

1
2
3
4
5
public class Comune
{
  public String prefisso { get; set; }
  public String descrizione { get; set; }
}

A questo punto siamo pronti: possiamo sfruttare la potenza di LINQ e popolare una lista di comuni con un’unica query.

Di seguito il metodo popolaComuni che serve al nostro scopo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public static List popolaComuni(string xmlFilePath)
{
  List lstComuni = new List();

  var com = from p in  XElement.Load(xmlFilePath).Elements("comuni")
                                 .Elements("comune")
                       orderby (string)p.Element("descrizione") ascending
                       select new Comune
                       {
                          prefisso = (string)p.Element("prefisso"),
                          descrizione = (string)p.Element("descrizione")
                       };

  foreach (var c in com)
    lstComuni.Add(c);

  return lstComuni;
}

Il punto chiave della query è l’accesso in cascata ai nodi del file xml tramite l’istruzione:

1
2
3
4
5
6
7
8
9
XElement.Load(nomeFileXml).Elements("comuni").Elements("comune")
</pre>
E' poi interessante notare come LINQ ci permetta di popolare una classe direttamente con i risultati della query.
<code lang="CSharp">..
 select new Comune
  {
    prefisso = (string)p.Element("prefisso"),
    descrizione = (string)p.Element("descrizione")
  };

Questo è forse l’aspetto più interessante in quanto, definendo una sola volta la new del nostro oggetto all’interno della query, otteniamo direttamente una lista di oggetti all’interno della nostra variabile com.

Potremmo utilizzare direttamente questa variabile nel nostro codice, ma per comodità carichiamo il tutto in una List con il ciclo for finale.

Oltre alla semplicità, c’è da dire che questo approccio con LINQ è anche molto più veloce in fase di esecuzione rispetto alla lettura di un file xml scorrendo i nodi come oggetti XmlNode. Un vantaggio notevole quando si trattano file di grandi dimensioni.

Category: .NET Svliluppo Tag:, ,

About Claudio

Claudio Marai is a co-founder of DevInterface.

After graduating in Computer Science has contributed to develop complex web applications based on Java/J2EE and desktop applications with the. NET framework for the Ministry of Justice and ultimately for the banking ambit.

The passion for web in recent years has led him to be interested in more modern frameworks such as Ruby on Rails and Django, and to a development approach based on agile methodologies such as eXtreme Programming and SCRUM.

4 thoughts on “LINQ: da xml a classi C#

  1. Aher

    List -> which namespace should be reference ?
    because if using System.Collection.Generic then strong type must be specify like List

  2. Alex

    You can use .ToList() function instead foreach circle :)

    List lstMunicipalities = (from p in …. select new Municipality()).ToList();

  3. Giganoide

    Il framework mette a disposizione l’oggetto XmlSerializer che serve propio a fare questo mestiere.

    Esempio:
    XmlSerializer ser = new XmlSerializer(typeof(Comuni));
    Comuni comuni;
    using (XmlReader reader = XmlReader.Create(path))
    {
    comuni = (Comuni) ser.Deserialize(reader);
    }

    Una volta in memoria è possibile utilizzare il linq.

Comments are closed.