CodeGym /Cours /C# SELF /Travailler avec XmlSeriali...

Travailler avec XmlSerializer pour la sérialisation en XML

C# SELF
Niveau 44 , Leçon 2
Disponible

1. Introduction

XML — abréviation de eXtensible Markup Language. Imaginez un JSON très strict et bavard, capable de répéter sans cesse «je suis structuré, crois-moi !». XML est un format texte où les données sont encadrées par des balises :

<Player>
  <Name>Aragorn</Name>
  <Health>100</Health>
</Player>

Pourquoi encore sérialiser des objets en XML de nos jours ?

  • XML reste largement utilisé pour l'intégration entre de gros systèmes (souvent "legacy") où on a besoin non seulement de structure, mais aussi de validation selon des schémas stricts (XSD).
  • XML est souvent utilisé dans des configurations d'entreprise (par exemple, App.config et Web.config dans les générations .NET plus anciennes).
  • XML convient parfaitement aux cas où la capacité de la structure de données à s'auto-décrire est importante.

Fait intéressant : XML a été conçu pour être aussi «extensible» et validable que possible — d'où son nom. Il peut être vérifié par rapport à un schéma, ce que JSON n'offre pas «out of the box».

XmlSerializer : le héros

En .NET, la sérialisation des objets en XML est assurée par la classe System.Xml.Serialization.XmlSerializer.

  • Il transforme les propriétés et champs publics d'un objet en éléments XML, et inversement : il reconstruit l'objet à partir du XML.
  • Il ne fonctionne qu'avec des types et membres publics.
  • Il ne sérialise pas les champs et propriétés privés — seulement ce qui est public !
  • Il exige qu'il y ait un constructeur sans paramètres pour la classe sérialisable.

Attention : Si votre classe ne respecte pas ces exigences, XmlSerializer ne pourra pas fonctionner avec elle — il lèvera une exception lors de la sérialisation ou de la désérialisation.

2. Exemple simple — sérialiser un objet en XML

Prenons comme exemple la sérialisation de notre classe préférée Player en XML.

Étape 1. On décrit la classe

public class Player
{
    public string Name { get; set; }
    public int Health { get; set; }
    public bool IsAlive { get; set; }

    // Important : il faut un constructeur public sans paramètres !
    public Player() { }

    // Optionnel : pratique pour faciliter l'utilisation
    public Player(string name, int health, bool isAlive)
    {
        Name = name;
        Health = health;
        IsAlive = isAlive;
    }
}

Étape 2. On sérialise dans un fichier

using System.Xml.Serialization;

Player aragorn = new Player("Aragorn", 100, true);

// 1. On crée le XmlSerializer pour le type Player
XmlSerializer serializer = new XmlSerializer(typeof(Player));

// 2. On ouvre le fichier pour écrire (il sera créé s'il n'existe pas)
using FileStream fs = new FileStream("player.xml", FileMode.Create);

// 3. On sérialise l'objet en XML
serializer.Serialize(fs, aragorn);

Résultat (player.xml):

<?xml version="1.0"?>
<Player xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Name>Aragorn</Name>
  <Health>100</Health>
  <IsAlive>true</IsAlive>
</Player>

Schéma visuel du processus le plus simple


Objet en mémoire  --->  XmlSerializer.Serialize()  --->  fichier XML sur le disque

3. Désérialisation — «on réanime» l'objet depuis le XML

Quand on a besoin de lire un objet précédemment sérialisé, le processus est l'inverse :

using FileStream fs = new FileStream("player.xml", FileMode.Open);
XmlSerializer serializer = new XmlSerializer(typeof(Player));
Player player = (Player)serializer.Deserialize(fs);

Console.WriteLine($"Nom: {player.Name}, Santé: {player.Health}, En vie: {player.IsAlive}");

Résultat : le programme affichera : Nom: Aragorn, Santé: 100, En vie: True

4. Sérialisation en chaîne — pas seulement dans un fichier

Sérialisation dans une chaîne

Parfois on ne veut pas écrire dans un fichier. Par exemple, on peut vouloir envoyer le XML sur le réseau ou l'afficher à l'écran.

using System.IO;
using System.Xml.Serialization;

Player player = new Player("Frodo", 42, true);

XmlSerializer serializer = new XmlSerializer(typeof(Player));
StringWriter stringWriter = new StringWriter();
serializer.Serialize(stringWriter, player);

string xmlString = stringWriter.ToString();
Console.WriteLine(xmlString); // Toute la chaîne XML — affichée à l'écran !

Désérialisation depuis une chaîne

De la même façon, on peut désérialiser un objet non pas depuis un fichier, mais depuis une chaîne :

string xml = "<Player Name=\"Frodo\"><HP>42</HP></Player>";
XmlSerializer serializer = new XmlSerializer(typeof(Player));

using StringReader stringReader = new StringReader(xml);
Player frodo = (Player)serializer.Deserialize(stringReader);
Console.WriteLine(frodo.Name); // Frodo

5. Personnaliser le XML : attributs pour contrôler la structure

Parfois le comportement par défaut ne vous convient pas. Le XML peut être trop verbeux ou les balises ne correspondent pas à ce qu'on veut. On utilise alors plusieurs attributs "magiques" qui indiquent au serializer comment représenter les membres de la classe.

Les plus utiles :

  • [XmlElement]
    — donne le nom de l'élément.
  • [XmlAttribute]
    — transforme le champ en attribut XML plutôt qu'en élément.
  • [XmlIgnore]
    — exclut la propriété de la sérialisation.
  • [XmlArray]
    et
    [XmlArrayItem]
    — contrôlent l'enveloppe et les éléments des collections.

Exemple d'utilisation :

public class Player
{
    [XmlAttribute]
    public string Name { get; set; }
    [XmlElement("HP")]
    public int Health { get; set; }
    [XmlIgnore]
    public bool IsTempSessionPlayer { get; set; }
}

XML résultant :

<Player Name="Aragorn">
  <HP>100</HP>
</Player>

Tableau des principaux attributs pour la sérialisation

Attribut Ce que ça influence Exemple d'utilisation
[XmlAttribute]
Transforme la propriété en un attribut XML
<Player Name="Aragorn">...</Player>
[XmlElement]
Change le nom de la balise
<HP>100</HP>
au lieu de
<Health>100</Health>
[XmlIgnore]
Exclut complètement la propriété de la sérialisation
[XmlArray]
Change le nom de l'enveloppe de la collection
<Heroes> ... </Heroes>
[XmlArrayItem]
Change le nom de l'élément de la collection
<Hero>...</Hero>

Exemple de sérialisation d'une collection complexe :

public class GameWorld
{
    [XmlArray("Heroes")]
    [XmlArrayItem("Hero")]
    public List<Player> Players { get; set; } = new List<Player>();
}

XML :

<GameWorld>
  <Heroes>
    <Hero Name="Legolas">
      <HP>90</HP>
    </Hero>
    <!-- ... -->
  </Heroes>
</GameWorld>

On en reparlera dans les prochaines leçons ! :P

Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION