Introduction à la sérialisation XML
La sérialisation est le processus de conversion d'un objet en un formulaire qui peut être transporté facilement. Par exemple, vous pouvez sérialiser un objet et le transporter sur Internet entre un client et un serveur à l'aide du protocole HTTP. À l'autre extrémité, la désérialisation reconstruit l'objet à partir du flux.
La sérialisation XML ne sérialise que les champs publics et les valeurs des propriétés d'un objet dans un flux XML. La sérialisation n'inclut pas d'informations de type. Par exemple, si vous avez un objet Book qui existe dans un espace de noms Library, rien ne garantit qu'il sera désérialisé dans un objet du même type.
Remarque La sérialisation XML ne convertit pas de méthodes, d'indexeurs, de champs privés ou de propriétés en lecture seule (sauf les collections en lecture seule). Pour sérialiser tous les champs et toutes les propriétés d'un objet, privés et publics, utilisez BinaryFormatter au lieu de la sérialisation XML.
La classe centrale de la sérialisation XML est la classe XmlSerializer et ses méthodes les plus importantes sont les méthodes Serialize et Deserialize. Le flux XML généré par la classe XmlSerializer est conforme à la recommandation du langage XSD (XML Schema Definition) 1.0 du World Wide Web Consortium disponible à l'adresse suivante : www.w3.org (en anglais). De plus, les types de données générés sont conformes au document intitulé « XML Schema Part 2: Datatypes. » (en anglais).
Les données dans vos objets sont décrites à l'aide de constructions de langage de programmation comme les classes, les champs, les propriétés, les types primitifs, les tableaux voir du code XML incorporé sous la forme d'objets XmlElement ou XmlAttribute. Vous avez l'option de créer vos propres classes annotées avec des attributs ou d'utiliser l'outil XML Schema Definition Tool pour générer les classes basées sur un schéma XML existant.
Si vous avez un schéma XML, vous pouvez exécuter l'outil XML Schema Definition Tool pour produire un ensemble de classes fortement typées au schéma et annoté avec des attributs. Lorsqu'une instance d'une telle classe est sérialisée, le code XML généré se conforme au schéma XML. À l'aide de cette classe, vous pouvez programmer en vous servant d'un modèle objet facilement manipulé tout en étant certain que le code XML généré se conforme au schéma XML. Cette solution remplace l'utilisation d'autres classes dans le .NET Framework, telles que les classes XmlReader et XmlWriter, pour analyser et écrire un flux XML. (Pour plus d'informations sur l'utilisation de ces classes, consultez le tableau dans Utilisation de XML dans le .NET Framework.) Ces classes vous permettent d'analyser n'importe quel flux XML. Par contre, utilisez la classe XmlSerializer lorsque le flux XML est censé se conformer à Schéma XML connu.
Les attributs contrôlent le flux XML généré par la classe XmlSerializer ce qui vous permet de définir l'espace de noms XML, le nom de l'élément, le nom de l'attribut etc. du flux XML. Pour plus d'informations sur ces attributs et sur la manière dont ils contrôlent la sérialisation XML, consultez Contrôle de la sérialisation XML à l'aide d'attributs. Pour obtenir un tableau des attributs utilisés pour le contrôle de code XML généré, consultez Attributs qui contrôlent la sérialisation XML.
La classe XmlSerializer peut sérialiser un objet davantage et générer un flux XML codé en SOAP. Le code XML généré se conforme à la section 5 du document du World Wide Web Consortium intitulé « Simple Object Access Protocol (SOAP) 1.1 » (en anglais) Pour plus d'informations sur ce processus, consultez Génération de messages SOAP à l'aide de la sérialisation XML. Pour obtenir un tableau des attributs qui contrôlent le code XML généré, consultez Attributs qui contrôlent la sérialisation codée en SOAP.
La classe XmlSerializer génère les messages SOAP créés par et passés aux services Web XML. Pour contrôler les messages SOAP, vous pouvez appliquer des attributs aux classes, aux valeurs de retour, aux paramètres et aux champs qui figurent dans un fichier de service Web XML (.asmx). Vous pouvez utiliser les attributs répertoriés dans « Attributs qui contrôlent la sérialisation XML » et « Attributs qui contrôlent la sérialisation codée en SOAP » car un service Web XML peut utiliser soit le style codé en SOAP, soit le style littéral. Pour plus d'informations sur l'utilisation d'attributs pour contrôler le code XML généré par un service Web XML, consultez Sérialisation XML à l'aide des services Web XML. Pour plus d'informations sur les services Web XML et SOAP, consultez Personnalisation des messages SOAP.
Sécurisation des applications XmlSerializer
Lors de la création d'une application qui utilise XmlSerializer, vous devez connaître les éléments suivants et leurs implications :
XmlSerializer crée des fichiers C# (fichiers .cs ) et les compile dans des fichiers .dll dans le répertoire nommé par la variable d'environnement TEMP ; la sérialisation se produit avec ces DLL.
Le code et les DLL sont vulnérables face à un processus nuisible lors de la création et de la compilation. Lors de l'utilisation d'un ordinateur qui exécute Microsoft Windows NT 4.0 ou une version ultérieure, il est parfois possible que deux utilisateurs partagent le répertoire temporaire. Le partage d'un répertoire temporaire présente des risques si (1) les deux comptes ont des privilèges de sécurité différents, et (2) le compte de privilège supérieur exécute une application à l'aide de XmlSerializer. Dans ce cas, un utilisateur peut enfreindre la sécurité de l'ordinateur en remplaçant soit le fichier .cs, soit .dll qui est compilé. Pour éliminer ce problème, veillez toujours à ce que chaque compte sur l'ordinateur possède son propre profil. Si c'est le cas, par défaut, la variable d'environnement TEMP pointera vers un répertoire différent pour chaque compte.
Si un utilisateur malveillant envoie un flux continu de données XML vers un serveur Web (une attaque de refus de service), XmlSerializer continuera à traiter les données jusqu'à ce que l'ordinateur manque de ressources.
Ce type d'attaque est éliminé si vous utilisez un ordinateur qui exécute les services IIS (Internet Information Services) et que votre application s'exécute dans IIS. IIS comporte une porte qui ne traite pas les flux dont la taille est supérieure à une taille déterminée (4 Ko par défaut). Si vous créez une application qui n'utilise pas IIS et qui désérialise à l'aide de XmlSerializer, vous devez implémenter une porte similaire qui empêche une attaque de refus de service.
XmlSerializer sérialise les données et exécute tout code à l'aide de n'importe quel type qui lui est attribué.
Un objet nuisible présente une menace sous deux formes. L'objet peut exécuter du code nuisible ou il peut injecter du code nuisible dans le fichier C# créé par XmlSerializer. Dans le premier cas, si un objet nuisible essaye d'exécuter une procédure destructrice, la sécurité d'accès au code permet d'empêcher tout dommage. Dans le deuxième cas, il existe une possibilité théorique qu'un objet nuisible parvienne d'une manière ou d'une autre à injecter du code dans le fichier C# créé par XmlSerializer. Bien que ce problème ait fait l'objet d'une attention rigoureuse et que ce type d'attaque soit improbable, vous devez prendre la précaution de ne jamais sérialiser des données à l'aide d'un type inconnu et qui n'est pas digne de confiance.
Les données sensibles sérialisées peuvent être vulnérables.
Après la sérialisation des données par XmlSerializer, celui-ci peut être stocké comme fichier XML ou d'autres magasins de données. Si votre magasin de données est disponible à d'autres processus ou s'il est visible sur un intranet ou Internet, les données peuvent être volées et utilisées à des fins malveillantes. Par exemple, si vous créez une application qui sérialise des commandes contenant des numéros de carte de crédit, les données sont particulièrement sensibles. Pour permettre d'empêcher cela, protégez toujours votre magasin de données et faites en sorte de préserver leur confidentialité.
Sérialisation d'une classe simple
L'exemple suivant montre une classe simple avec un champ public.
Public Class OrderForm
Public OrderDate As DateTime
End Class
[C#]
public class OrderForm{
public DateTime OrderDate;
}
Lorsqu'une instance de cette classe est sérialisée, elle peut ressembler à ce qui suit.
<OrderForm>
<OrderDate>12/12/01</OrderDate>
</OrderForm>
Pour obtenir d'autres exemples de sérialisation, consultez Exemples de sérialisation XML.
Éléments pouvant être sérialisés
Les éléments suivants peuvent être sérialisés à l'aide de la classe XmLSerializer.
- Les propriétés en lecture/écriture publiques et les champs de classes publiques.
- Les classes qui implémentent ICollection ou IEnumerable. (Notez que seules les collections sont sérialisées, pas les propriétés publiques.)
- Les objets XmlElement.
- Les objets XmlNode.
- Les objets DataSet.
Sérialisation et désérialisation d'objets
Pour sérialiser un objet, créez d'abord l'objet qui doit être sérialisé et définissez ses propriétés et ses champs publics. Pour ce faire, vous devez déterminer le format de transport dans lequel le flux XML doit être stocké - soit sous forme de flux, soit sous forme de fichier. Par exemple, si le flux XML doit être enregistré de façon permanente, créez un objet FileStream. Lorsque vous désérialisez un objet, le format de transport détermine si vous créez un objet de flux ou un fichier objet. Une fois le format de transport déterminé, vous pouvez appeler les méthodes Serialize ou Deserialize selon vos besoins.
Pour sérialiser un objet
Créez l'objet et définissez ses propriétés et ses champs publics.
Construisez une classe XmlSerializer à l'aide du type de l'objet. Pour plus d'informations, consultez les constructeurs de classe XmlSerializer.
Appelez la méthode Serialize pour générer soit un flux XML, soit une représentation fichier des champs et propriétés publics de l'objet. L'exemple suivant crée un fichier.
Dim myObject As MySerializableClass = New MySerializableClass() ' Insert code to set properties and fields of the object. Dim mySerializer As XmlSerializer = New XmlSerializer(GetType(MySerializableClass)) ' To write to a file, create a StreamWriter object. Dim myWriter As StreamWriter = New StreamWriter("myFileName.xml") mySerializer.Serialize(myWriter, myObject) [C#] MySerializableClass myObject = new MySerializableClass(); // Insert code to set properties and fields of the object. XmlSerializer mySerializer = new XmlSerializer(typeof(MySerializableClass)); // To write to a file, create a StreamWriter object. StreamWriter myWriter = new StreamWriter("myFileName.xml"); mySerializer.Serialize(myWriter, myObject);
Pour désérialiser un objet
Construisez une classe XmlSerializer à l'aide du type de l'objet à désérialiser.
Appelez la méthode Deserialize pour produire un réplica de l'objet. Lors de la désérialisation, vous devez effectuer un cast de l'objet retourné dans le type de l'objet d'origine de la manière illustrée dans l'exemple suivant. L'exemple suivant désérialise l'objet dans un fichier, même s'il peut être également désérialisé dans un flux.
Dim myObject As MySerializableClass ' Constructs an instance of the XmlSerializer with the type ' of object that is being deserialized. Dim mySerializer As XmlSerializer = New XmlSerializer(GetType(MySerializableClass)) ' To read the file, creates a FileStream. Dim myFileStream As FileStream = _ New FileStream("myFileName.xml", FileMode.Open) ' Calls the Deserialize method and casts to the object type. myObject = CType( _ mySerializer.Deserialize(myFileStream), MySerializableClass) [C#] MySerializableClass myObject; // Constructs an instance of the XmlSerializer with the type // of object that is being deserialized. XmlSerializer mySerializer = new XmlSerializer(typeof(MySerializableClass)); // To read the file, creates a FileStream. FileStream myFileStream = new FileStream("myFileName.xml", FileMode.Open); // Calls the Deserialize method and casts to the object type. myObject = (MySerializableClass) mySerializer.Deserialize(myFileStream)
Pour obtenir d'autres exemples de sérialisation XML, consultez Exemples de sérialisation XML.
Avantages de la sérialisation XML
La classe XmlSerializer vous donne un contrôle complet et souple lorsque vous sérialisez un objet au format XML. Si vous créez un service Web XML, vous pouvez appliquer les attributs qui contrôlent la sérialisation aux classes et aux membres pour garantir que la sortie XML se conforme à un schéma spécifique.
Par exemple, la classe XmlSerializer vous permet d'effectuer les opérations suivantes :
- Spécifier si un champ ou une propriété doit être codée en tant qu'attribut ou élément.
- Spécifier un espace de noms XML à utiliser.
- Spécifier le nom d'un élément ou d'un attribut si un nom de champ ou de propriété ne convient pas.
Un autre avantage de la sérialisation XML est l'absence de contrainte sur les applications que vous développez tant que le flux XML qui est généré se conforme à un schéma donné. Imaginez un schéma qui est utilisé pour décrire des livres - il comprend un élément titre, auteur, éditeur et numéro ISBN. Vous pouvez développer une application qui traite les données XML de la façon dont vous voulez - par exemple, sous forme de commande de livres ou d'inventaire de livres. Dans l'un ou l'autre cas, la seule exigence est celle de la conformité du flux XML au schéma XSD spécifié.
Considérations relatives à la sérialisation XML
Les éléments suivants doivent être envisagés lors de l'utilisation de la classe XmLSerializer :
- Les données sérialisées contiennent uniquement les données elles-mêmes et la structure de vos classes. Les informations d'assembly et d'identité de type ne sont pas incluses.
- Seuls les champs et propriétés publics peuvent être sérialisés. S'il vous faut sérialiser des données non publiques, utilisez la classe BinaryFormatter plutôt que la sérialisation XML.
- Une classe doit posséder un constructeur par défaut à sérialiser par XmlSerializer.
- Les méthodes ne peuvent pas être sérialisées.
- XmlSerializer peut traiter les classes qui implémentent IEnumerable ou ICollection différemment si celles-ci répondent à certaines exigences. Une classe qui implémente IEnumerable doit implémenter une méthode Add publique qui prend un seul paramètre. Le paramètre de la méthode Add doit être cohérent (polymorphe) avec le type retourné à partir de la propriété IEnumerator.Current retournée à partir de la méthode GetEnumerator. Une classe qui implémente ICollection en plus de IEnumerable (telle que CollectionBase) doit avoir une propriété indexée Item publique (un indexeur dans C#) qui prend un entier, ainsi qu'une propriété Count publique d'un entier de type. Le paramètre passé à la méthode Add doit être du même type que celui retourné à partir de la propriété Item ou l'une des bases de ce type. Pour les classes qui implémentent ICollection, les valeurs à sérialiser seront extraites à partir de la propriété Item indexée plutôt qu'en appelant GetEnumerator. Remarquez également que les champs et propriétés publics ne seront pas sérialisés à l'exception des champs publics qui retournent une autre classe de collection (une classe implémentant ICollection). Pour obtenir un exemple, consultez Exemples de sérialisation XML.
Mappage de types de données XSD
Le document du World Wide Web Consortium (www.w3.org) intitulé « XML Schema Part 2: Datatypes » (en anglais) spécifie les types de données simples qui sont autorisés dans un schéma de langage XSD (XML Schema Definition). Pour la plupart de ces types (par exemple, int et decimal), il existe un type de données correspondant dans le .NET Framework. Cependant, certains types de données XML ne possèdent pas de type de données correspondant dans le .NET Framework (le type de données NMTOKEN par exemple). Dans ces cas-là, si vous utilisez l'outil XML Schema Definition Tool (Xsd.exe) pour générer des classes à partir d'un schéma, un attribut approprié est appliqué à un membre de type string. Sa propriété DataType prend la valeur du nom du type de données XML. Par exemple, si un schéma contient un élément nommé « MyToken » avec le type de données XML NMTOKEN, la classe générée peut contenir un membre, comme le montre l'exemple suivant.
<XmlElement(DataType:="NMTOKEN")>
Public MyToken As String
[C#]
[XmlElement(DataType = "NMTOKEN")]
public string MyToken;
De même, si vous créez une classe qui doit se conformer à un schéma XSD spécifique, vous devez appliquer l'attribut approprié et attribuer à sa propriété DataType le nom de type de données XML souhaité.
Pour obtenir une liste complète des mappages de type, consultez la propriété DataType pour n'importe laquelle des classes d'attribut suivantes : SoapAttributeAttribute, SoapElementAttribute, XmlArrayItemAttribute, XmlAttributeAttribute, XmlElementAttribute ou XmlRootAttribute.
Voir aussi
Sérialisation XML et SOAP | XMLSerializer.Serialize | BinaryFormatter | Sérialisation binaire | Sérialisation d'objets | XmlSerializer | FileStream | Exemples de sérialisation XML