Developer

Persist data with the XMLSerializer class

The System.Xml.Serialization namespace provides the basic functionality of persisting an object as XML. Take a look at how you can use this approach.

Microsoft recognized the need to persist data by including serialization functionality in the .NET Framework with the System.Runtime.Serialization, which provides the framework for developing custom serialization solutions, and the System.Xml.Serialization namespaces. The System.Xml.Serialization namespace provides the basic functionality of persisting an object as XML. Let's take a closer look at using this approach.

The universal appeal of XML

XML serialization is the process of converting an object's public properties and fields to a serial format (in this case, XML) for storage or transport. Deserialization recreates the object in its original state from the XML output. Thus, you can think of serialization as a way of saving the state of an object into a stream or buffer.

The two common usages of serialization are persistence and data exchange. Persistence refers to the process of saving data between a user's session. The data is stored (serialization) when the application is closed, and it's reloaded (deserialization) when the user returns. Data exchange is the process of making data available to another system. This is easily accomplished with serialization and XML.

The data in your objects is described using programming language constructs such as classes, fields, properties, primitive types, arrays, and even embedded XML in the form of System.Xml.XmlElement or System.Xml.XmlAttribute objects.

The central class of the System.Xml.Serialization namespace is XmlSerializer. It contains classes for working with the various aspects of XML and utilizing SOAP as well, but the XmlSerializer class is our focus.

XmlSerializer

The XmlSerializer class allows you to serialize and deserialize objects into and from XML documents. It enables you to control how objects are encoded into XML. The class constructor accepts the object type to serialize. The following C# code shows the constructor in action:

XmlSerializer ser = new XmlSerializer(typeof(objectToSerialize));

Here's the VB.NET equivalent:

Dim ser As New XmlSerializer(GetType(objectToSerialize))

The actual serialization process is performed with the XmlSerializer class' Serialize method. This method has six signatures that allow you to use TextWriter, Stream, and XmlWriter objects in the serialization process. The following example code shows how it may be utilized. The example serializes an object to a file on the local disk drive. The code for the classes utilized is listed first, followed by the actual serialization code.

using System;
namespace BuilderSerialization {
public class Address {
public Address() {}
public string Address1;
public string Address2;
public string City;
public string State;
public string Zip;
public string Country;
} }
using System;
namespace BuilderSerialization {
public class Author {
public Author() { }
public string FirstName;
public string MiddleName;
public string LastName;
public string Title;
public string Gender;
public Address AddressObject;
} }
namespace BuilderSerialization {
public class Book {
public Book() { }
public string Title;
public Author AuthorObject;
public string ISBN;
public double RetailPrice;
public string Publisher;
}}
using System;
using System.Xml.Serialization;
using System.IO;
namespace BuilderSerialization {
class TestClass {
static void Main(string[] args) {
Book BookObject = new Book();
XmlSerializer ser = new XmlSerializer(typeof(Book));
TextWriter writer = new StreamWriter("booktest.xml");
BookObject.Title = "Practical LotusScript";
BookObject.ISBN = "1884777767 ";
BookObject.Publisher = "Manning Publications";
BookObject.RetailPrice = 43.95;
BookObject.AuthorObject = new Author();
BookObject.AuthorObject.FirstName = "Tony";
BookObject.AuthorObject.LastName = "Patton";
BookObject.AuthorObject.Gender = "Male";
BookObject.AuthorObject.AddressObject = new Address();
BookObject.AuthorObject.AddressObject.Address1 = "1 Main Street";
BookObject.AuthorObject.AddressObject.City = "Anywhere";
BookObject.AuthorObject.AddressObject.State = "KY";
BookObject.AuthorObject.AddressObject.Zip = "40000";
BookObject.AuthorObject.AddressObject.Country = "USA";
ser.Serialize(writer, BookObject);
writer.Close();
} } }

This code utilizes three objects that are combined into one, so the serialization process produces one XML document. Here is the XML created by the sample code:

<?xml version="1.0" encoding="utf-8"?>
<Book xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Title>Practical LotusScript</Title>
<AuthorObject>
<FirstName>Tony</FirstName>
<LastName>Patton</LastName>
<Gender>Male</Gender>
<AddressObject>
<Address1>1 Main Street</Address1>
<City>Anywhere</City>
<State>KY</State>
<Zip>40000</Zip>
<Country>USA</Country>
</AddressObject>
</AuthorObject>
<ISBN>1884777767 </ISBN>
<RetailPrice>43.95</RetailPrice>
<Publisher>Manning Publications</Publisher>
</Book>

Notice that the serialization process handles the nesting of object data. This places the data in a usable format that may be easily loaded (deserialized) when needed or exchanged with another system. When exchanging the data, the other system will need to know the format of the XML (if not already known). This may be provided via an XML schema file. The .NET Framework includes the schema generation tool XSD.exe that may be used to generate a schema file for the XML generated via serialization.

Here's the example code as VB.NET:

Public Class Address
Public Address1 As String
Public Address2 As String
Public City As String
Public State As String
Public Zip As String
Public Country As String
End Class
Public Class Author
Public FirstName As String
Public MiddleName As String
Public LastName As String
Public Title As String
Public Gender As String
Public AddressObject As Address
End Class
Public Class Book
Public AuthorObject As Author
Public Title As String
Public ISBN As String
Public RetailPrice As Double
Public Publisher As String
End Class
Imports System.Xml.Serialization
Imports System.IO
Module Module1
Sub Main()
Dim BookObject As New Book
Dim ser As New XmlSerializer(GetType(Book))
Dim writer As New StreamWriter("booktest.xml")
With BookObject
.Title = "Practical LotusScript"
.ISBN = "1884777767 "
.Publisher = "Manning Publications"
.RetailPrice = 43.95
.AuthorObject = New Author
.AuthorObject.FirstName = "Tony"
.AuthorObject.LastName = "Patton"
.AuthorObject.Gender = "Male"
.AuthorObject.AddressObject = New Address
.AuthorObject.AddressObject.Address1 = "1 Main Street"
.AuthorObject.AddressObject.City = "Anywhere"
.AuthorObject.AddressObject.State = "KY"
.AuthorObject.AddressObject.Zip = "40000"
.AuthorObject.AddressObject.Country = "USA"
End With
ser.Serialize(writer, BookObject)
writer.Close()
End Sub
End Module

Providing direction

The serialization process spits out standard XML with data members as elements when left on its own, but you may customize the XML output by placing attributes within the class code. This allows you to create attributes instead of XML elements or tell the system to simply ignore an element. The following reworking of the VB.NET book class provides an example:

Public Class Book
Public AuthorObject As Author
Public Title As String
<System.Xml.Serialization.XmlAttribute()> _
Public ISBN As String
<System.Xml.Serialization.XmlIgnoreAttribute()> _
Public RetailPrice As Double
Public Publisher As String
End Class

This code tells the system to treat the ISBN member as an XML attribute and ignore the RetailPrice member when generating the XML. The result of these changes is reflected in the XML:

<?xml version="1.0" encoding="utf-8"?>
<Book xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ISBN="1884777767 ">
<AuthorObject>
<FirstName>Tony</FirstName>
<LastName>Patton</LastName>
<Gender>Male</Gender>
<AddressObject>
<Address1>1 Main Street</Address1>
<City>Anywhere</City>
<State>KY</State>
<Zip>40000</Zip>
<Country>USA</Country>
</AddressObject>
</AuthorObject>
<Title>Practical LotusScript</Title>
<Publisher>Manning Publications</Publisher>
</Book>

This is the C# equivalent:

public class Book {
public Book() { }
public string Title;
public Author AuthorObject;
[System.Xml.Serialization.XmlAttribute()]
public string ISBN;
[System.Xml.Serialization.XmlIgnoreAttribute()]
public double RetailPrice;
public string Publisher;
}

This provides a peek at the available attributes. Refer to your .NET documentation for a complete list of these identifiers.

Put it in reverse

Deserializing the data is a simple process accomplished via the Deserialize method of the XmlSerializer class. The following VB.NET snippet accomplishes the feat with our example output:

Dim BookObject As New Book
Dim ser As New XmlSerializer(GetType(Book))
Dim fs As New System.IO.FileStream("booktest.xml", FileMode.Open)
Dim reader As New System.XML.XmlTextReader(fs)
BookObject = CType(ser.Deserialize(reader), Book)

This places the data in memory to be used when necessary. This is the C# equivalent:

XmlSerializer ser = new XmlSerializer(typeof(Book));
System.IO.FileStream fs = new System.IO.FileStream("booktest.xml",
FileMode.Open);
System.Xml.XmlTextReader reader = new System.Xml.XmlTextReader(fs);
Book BookObject = (Book)(ser.Deserialize(reader));

TechRepublic's free .NET newsletter, delivered each Wednesday, contains useful tips and coding examples on topics such as Web services, ASP.NET, ADO.NET, and Visual Studio .NET. Automatically sign up today!

About Tony Patton

Tony Patton has worn many hats over his 15+ years in the IT industry while witnessing many technologies come and go. He currently focuses on .NET and Web Development while trying to grasp the many facets of supporting such technologies in a productio...

Editor's Picks

Free Newsletters, In your Inbox