C# Tutorial - XML Serialization
A long while ago we posted a tutorial on how to serialize objects to a binary file. While this is very useful, unfortunately the resulting file is not very human readable. In this tutorial, I'm going to demonstrate how to serialize your own objects to and from an XML file.
| Since .NET can use reflection to get property names, basic serialization is unbelievably simple. It only gets slightly difficult when you want to name your XML tags differently than your property names (but still not very hard). If you've ever used an XML serialization package in C++ like boost, tinyXML, or libXML2, you'll see how comparatively easy C# is to use. |
Let's start with a basic example. Below is an object that stores some information about a movie.
{
public string Title
{ get; set; }
public int Rating
{ get; set; }
public DateTime ReleaseDate
{ get; set; }
}
All right, now that we have an object, let's write a function that will save it to XML.
{
XmlSerializer serializer = new XmlSerializer(typeof(Movie));
TextWriter textWriter = new StreamWriter(@"C:\movie.xml");
serializer.Serialize(textWriter, movie);
textWriter.Close();
}
The first thing I do is create an XMLSerializer (located in the System.Xml.Serialization namespace) that will serialize objects of type Movie. The XMLSerializer will serialize objects to a stream, so we'll have to create one of those next. In this case, I want to serialize it to a file, so I create a TextWriter. I then simply call Serialize on the XMLSerializer passing in the stream (textWriter) and the object (movie). Lastly I close the TextWriter because you should always close opened files. That's it! Let's create a movie object and see how this is used.
{
Movie movie = new Movie();
movie.Title = "Starship Troopers";
movie.ReleaseDate = DateTime.Parse("11/7/1997");
movie.Rating = 6.9f;
SerializeToXML(movie);
}
static public void SerializeToXML(Movie movie)
{
XmlSerializer serializer = new XmlSerializer(typeof(Movie));
TextWriter textWriter = new StreamWriter(@"C:\movie.xml");
serializer.Serialize(textWriter, movie);
textWriter.Close();
}
After this code executes, we'll have an XML file with the contents of our movie object.
<Movie xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Title>Starship Troopers</Title>
<Rating>6.9</Rating>
<ReleaseDate>1997-11-07T00:00:00</ReleaseDate>
</Movie>
If you noticed, all of the XML tag names are the same as the property names. If we want to change those, we can simply add an attribute above each property that sets the tag name.
{
[XmlElement("MovieName")]
public string Title
{ get; set; }
[XmlElement("MovieRating")]
public float Rating
{ get; set; }
[XmlElement("MovieReleaseDate")]
public DateTime ReleaseDate
{ get; set; }
}
Now when the same code is executed again, we get our custom tag names.
<Movie xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<MovieName>Starship Troopers</MovieName>
<MovieRating>6.9</MovieRating>
<MovieReleaseDate>1997-11-07T00:00:00</MovieReleaseDate>
</Movie>
Sometimes, in XML, you want information stored as an attribute of another tag instead of a tag by itself. This can be easily accomplished with another property attribute.
{
[XmlAttribute("MovieName")]
public string Title
{ get; set; }
[XmlElement("MovieRating")]
public float Rating
{ get; set; }
[XmlElement("MovieReleaseDate")]
public DateTime ReleaseDate
{ get; set; }
}
With this code, MovieName will now be an attribute on the Movie tag.
<Movie xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
MovieName="Starship Troopers">
<MovieRating>6.9</MovieRating>
<MovieReleaseDate>1997-11-07T00:00:00</MovieReleaseDate>
</Movie>
Let's move on to something a little more interesting. Let's create another movie and serialize a List of them to our XML file. Here's the modified code to do just that:
{
Movie movie = new Movie();
movie.Title = "Starship Troopers";
movie.ReleaseDate = DateTime.Parse("11/7/1997");
movie.Rating = 6.9f;
Movie movie2 = new Movie();
movie2.Title = "Ace Ventura: When Nature Calls";
movie2.ReleaseDate = DateTime.Parse("11/10/1995");
movie2.Rating = 5.4f;
List<Movie> movies = new List<Movie>() { movie, movie2 };
SerializeToXML(movies);
}
static public void SerializeToXML(List<Movie> movies)
{
XmlSerializer serializer =
new XmlSerializer(typeof(List<Movie>));
TextWriter textWriter = new StreamWriter(@"C:\movie.xml");
serializer.Serialize(textWriter, movies);
textWriter.Close();
}
Now we have XML that looks like this:
<ArrayOfMovie xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Movie MovieName="Starship Troopers">
<MovieRating>6.9</MovieRating>
<MovieReleaseDate>1997-11-07T00:00:00</MovieReleaseDate>
</Movie>
<Movie MovieName="Ace Ventura: When Nature Calls">
<MovieRating>5.4</MovieRating>
<MovieReleaseDate>1995-11-10T00:00:00</MovieReleaseDate>
</Movie>
</ArrayOfMovie>
Ok, so you can see how easy it is to get your objects into an XML document. Let's now look at how to read an XML document back into our objects - deserialization. The process of deserializing is very similar to what we did for serialization.
{
XmlSerializer deserializer =
new XmlSerializer(typeof(List<Movie>));
TextReader textReader = new StreamReader(@"C:\movie.xml");
List<Movie> movies;
movies = (List<Movie>)deserializer.Deserialize(textReader);
textReader.Close();
return movies;
}
Just like before, we first create an XmlSerializer that can deserialize objects of type List<Movie>. The XmlSerializer also deserializes from a stream, so we create a file stream from our XML file. We then simply call Deserialize on the stream and cast the output to our desired type. Now the movies List is populated with objects that we previously serialized to the XML file.
The deserializer is very good at handling missing pieces of information in your XML file. Let's say the second movie didn't have the MovieName attribute on the Movie tag. When the XML file is deserialized, it simply populates that field with null. If MovieRating wasn't there, you'd receive 0. Since a DateTime object can't be null, if MovieReleaseDate was missing, you'd receive DateTime.MinValue (1/1/0001 12:00:00AM).
If the XML document contains invalid syntax, like say the first opening Movie tag was missing, the Deserialize call will fail with an InvalidOperationException. It will also be kind enough to specify the location in the file where it encountered the error (line number, column number).
One thing to remember is that the basic XML serialization won't maintain references. Let's say I populated my movies list with the same movie reference multiple times:
movie.Title = "Starship Troopers";
movie.ReleaseDate = DateTime.Parse("11/7/1997");
movie.Rating = 6.9f;
List<Movie> movies = new List<Movie>() { movie, movie };
Now I have a list containing two of the exact same movie reference. When I serialize and deserialize this list, it will be converted to two separate instances of the movie object - they would just have the same information. Along this same line, the XMLSerializer also doesn't support circular references. If you need this kind of flexibility, you should consider binary serialization.
There's still a lot to cover when it comes to XML serialization, but I think this tutorial covers enough of the basics to get things rolling. If you've got questions or anything else to say, leave us a comment.
Posted in C#, All Tutorials by The Reddest |

June 22nd, 2008 at 8:59 am
Thank you very much!
Very clear.
June 22nd, 2008 at 9:01 pm
TextWriter implements IDisposable; this code would be safer if it used the using statement.
June 23rd, 2008 at 4:39 am
I am doubt that it is possible deserilize the XML file without doing the serilize object? That means if I have a XML file created manually and then I just want to get the object information in the project(read only), is it possible? And how?
June 23rd, 2008 at 4:00 pm
@Bill Sorensen,
You’re absolutely right. I’ll modify the code examples to use the ‘using’ statement. That also would eliminate the need for the Close() call since the TextWriter closes itself when it’s disposed.
June 23rd, 2008 at 4:05 pm
@Yudy,
The deserializer does not need XML that was created by the serializer. You can use any manually created XML document, just as long as the elements have matching property names.
June 24th, 2008 at 1:52 am
@Reddest,
Thank you very much.
As you said if the elements match the property names, I can deserialize the XML document. So this means I cannot use the deserializer in .NET like XmlSerializer.Deserializer()? Can you give me an example to clarify it?
June 24th, 2008 at 10:07 am
Let’s say I have a hand written XML document like this:
<MyObject>
<MyPropertyA>10</MyPropertyA>
<MyPropertyB>20</MyPropertyB>
</MyObject>
And I have a C# object like this:
{
public int MyPropertyA {get; set;}
public int MyPropertyB {get; set;}
}
I can deserialize that XML document into my object using the following code:
new XmlSerializer(typeof(MyObject));
TextReader textReader = new StreamReader(@”C:\myXMLDoc.xml”);
MyObject myObj =
(MyObject)deserializer.Deserialize(textReader);
textReader.Close();
Since the XML document has the correct root node and has tags that match property names of my object, everything will work fine. If I changed the root node of my XML document to something like this:
<SomeOtherObject>
<MyPropertyA>10</MyPropertyA>
<MyPropertyB>20</MyPropertyB>
</SomeOtherObject>
the deserialization won’t work, because it will expect the root node to be named “MyObject”. However, you can still make this work by modifying the object to include what the root node is supposed to be named:
public class MyObject
{
public int MyPropertyA {get; set;}
public int MyPropertyB {get; set;}
}
Now we’re saying that even though the object is named “MyObject”, it will be called “SomeOtherObject” inside the XML document. And again, everything will work.
Hope this clears stuff up.
July 14th, 2008 at 5:53 am
Well..
And if i want
6,9
07-11-1997
??
(Custom DateTime and Flot number format)..
July 16th, 2008 at 10:00 am
This explanation has been very helpful and is nice and clear, thanks!
However, a complete code listing at the bottom with all the usings included, and where the code blocks should be placed in either a single file or in Visual Studio, would be even more helpful to us newbies.
July 18th, 2008 at 2:42 am
thanks for the great article.
in your example above, if i want to set attribute for element name lets say Rating, how can i do that? or do i have to create Rating as Class and apply attribute there? i think i can do that way but creating new class just to fulfill that doesn’t seem quite right.
any suggestion?
cheers
July 30th, 2008 at 1:04 pm
Can I do deserialize and deserialize specific node not entrie XML doc?
for example I want to deserialzie only data in below xml file. Can it be done?
20
20
July 30th, 2008 at 5:57 pm
Sorry Ramki, but the comment system strips < and >. Refer to this post on how to put xml and other code in the comments.
September 4th, 2008 at 11:42 pm
This is a great tutorial I found.
Thanks a lot to provide this kind of clear tutorial.
September 8th, 2008 at 1:08 am
dear sir
Request you to solve my issue.i.e. Let me know how to use jquery inside a xml file.if iam using so its giving err0r as
1.$ is not defined
2.script is not defined
September 16th, 2008 at 4:45 am
Is there any way to serialize an object that has private or internal set accessors, e.g:
public propertyname {private set; get; }
I can’t seem to get it to work.