Tutorial: C# XML Serialization


Almost every decent sized project in any programming language winds up having at least one configuration file. XML is a standard we often rely on because it’s generally perfect for the job. However, most people end up simply working with the XML file like they would any other file or simply scanning along each part of the “tree”. XML Serialization can take care of a lot of these instances with much better results, by providing an actual class interpretation of the configuration file. Let me show you.

Source Code

using System;
using System.Collections;
using System.Collections.Generic;
using System.Xml.Serialization;
using System.IO;
    // Define what the XML root will be
    [XmlRoot("ConfigRoot")]
    public class Config
    {
        // This attribute enables the ArrayList to be serialized:
        [XmlArray("Kids")]
        // Explicitly tell the serializer to expect the Item class
        // so it can be properly written to XML from the collection:
        [XmlArrayItem("kid", typeof(Kid))]

        public ArrayList _kids;
        // Dictionary of ours Kids which a String key
        private Dictionary<string, Kid> _kidDict;

        public Config()
        {
            this._kids = new ArrayList();
            this._kidDict = new Dictionary<String, Kid>();
        }

        public void AddKid(Kid kid)
        {
            this._kids.Add(kid);
            this._kidDict.Add(kid.Name, kid);
        }

        /// <summary>
        /// We'll use this to grab a kid by name.
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public Kid GetKid(String name)
        {
            return this._kidDict[name];
        }

        /// <summary>
        /// This will create our Kid Dictionary.
        /// It simply loops through the private _kids ArrayList and adds each kid.
        /// </summary>
        public void CreateKidDict()
        {
            //Empty the dictionary of Kid()'s before we rebuild it.
            this._kidDict = new Dictionary();

            for (int i = 0; i < this._kids.Count; i++)
            {
                Kid kid = this._kids[i] as Kid;

                this._kidDict.Add(kid.Name, kid);
            }
        }

        /// <summary>
        /// We'll simply pass the file path of where we want to save the config.
        /// </summary>
        /// <param name="filepath"></param>
        public void SerializeToXML(String filepath)
        {
            XmlSerializer serializer = new XmlSerializer(typeof(Config));
            TextWriter textWriter = new StreamWriter(filepath);
            serializer.Serialize(textWriter, this);
            textWriter.Close();

        }

        /// <summary>
        /// We'll pass the file path of where our config is stored.
        /// </summary>
        /// <param name="filepath"></param>
        /// <returns></returns>
        public Config DeserializeFromXML(String filepath)
        {
            XmlSerializer deserializer = new XmlSerializer(typeof(Config));
            TextReader textReader = new StreamReader(filepath);
            Object obj = deserializer.Deserialize(textReader);

            // Create the new Config that we'll return
            Config myNewConfig = (Config)obj;

            // We'll call the CreateKidDict now so that we already
            // have our Kid Dictionary ready to go.
            myNewConfig.CreateKidDict();

            return myNewConfig;
        }
    }
    public class Kid
    {
        [XmlElement("Name")]
        private String name;
        [XmlElement("Age")]
        private int age;

        public Kid()
        {

        }

        public Kid(String name, int age)
        {
            this.Name = name;
            this.Age = age;
        }

        public String Name
        {
            get { return name; }
            set { name = value; }
        }

        public int Age
        {
            get { return age; }
            set { age = value; }
        }
    }

Reviewing Code Line by Line

I know that on this web page, the code looks like quite a lot for some of you out there, but it’s actually not. It’s honestly quite small. We’ll start with the “imports”. These 5 imports are the only imports you’ll actually need. You won’t need them on every page, but if you download the source, you’ll see where each is needed/used. You needs the Collections series for the Dictionary we are going to make and the IO so we can read/write our configuration file.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Xml.Serialization;
using System.IO;

See? It’s already starting off fairly simple. Next, we create a class that is going to be our config. This means we have to design how each component is going to match up to it’s counterpart in the XML config. To be honest, this class is going to also generate the config, so that we’ll never even need to manually edit the config file, but we could if we wanted to.

The first thing we have to do is define our root. All we are simply doing is saying that the root of our configuration file will be “ConfigRoot”.

    // Define what the XML root will be
    [XmlRoot("ConfigRoot")]
    public class Config
    {

Next, we’ll define an ArrayList we are going to make as well as a Dictionary. I could explain how this works, but I think the code example shows it pretty clear. Kids will be the name of the “ArrayList” in the config and will have a series of kid‘s within it.

The one thing I would like to note however, is that the reason I am making both an ArrayList and a Dictionary for something that should seemingly just need a Dictionary is because currently you can’t Serialize a Dictionary, but you can Serialize a List. There are Dictionary classes that have been created to be Serialized or ways to get around this issue, but this tutorial is more about showing you the basics of XML Serialization, not a tutorial showing you how to most efficiently get a Dictionary through Serialization and into an XML Config, etc.

        // This attribute enables the ArrayList to be serialized:
        [XmlArray("Kids")]
        // Explicitly tell the serializer to expect the Item class
        // so it can be properly written to XML from the collection:
        [XmlArrayItem("kid", typeof(Kid))]

        public ArrayList _kids;
        // Dictionary of ours Kids which a String key
        private Dictionary<string, Kid> _kidDict;

We’re going to make some generic methods to add a kid, etc but the main two I want you to take a look at now are the two methods we use to create and work with our Kid Dictionary.

We’re going to create a method called GetKid() to retrieve a Kid by name. Then we’re going to create a CreateKidDict() method. We’ll simply loop through the Kid‘s in our Kid ArrayList and then insert into the Kid Dictionary with their Name as the key.

        /// <summary>
        /// We'll use this to grab a kid by name.
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public Kid GetKid(String name)
        {
            return this._kidDict[name];
        }

        /// <summary>
        /// This will create our Kid Dictionary.
        /// It simply loops through the private _kids ArrayList and adds each kid.
        /// </summary>
        public void CreateKidDict()
        {
            //Empty the dictionary of Kid()'s before we rebuild it.
            this._kidDict = new Dictionary();

            for (int i = 0; i < this._kids.Count; i++)
            {
                Kid kid = this._kids[i] as Kid;

                this._kidDict.Add(kid.Name, kid);
            }
        }

The last two methods within this class are pretty self explanatory as well. We are just creating a method to Serialize our Config class to XML. Then, we’ll call the method to De-serialize the XML back into an instance of the Config class. The only note I’d like to make is the fact that we call the CreateKidDict() method on our new Config before returning it. The reason to that is because we want the Dictionary of our Kid‘s to already be pre-populated.

        /// <summary>
        /// We'll simply pass the file path of where we want to save the config.
        /// </summary>
        /// <param name="filepath"></param>
        public void SerializeToXML(String filepath)
        {
            XmlSerializer serializer = new XmlSerializer(typeof(Config));
            TextWriter textWriter = new StreamWriter(filepath);
            serializer.Serialize(textWriter, this);
            textWriter.Close();

        }

        /// <summary>
        /// We'll pass the file path of where our config is stored.
        /// </summary>
        /// <param name="filepath"></param>
        /// <returns></returns>
        public Config DeserializeFromXML(String filepath)
        {
            XmlSerializer deserializer = new XmlSerializer(typeof(Config));
            TextReader textReader = new StreamReader(filepath);
            Object obj = deserializer.Deserialize(textReader);

            // Create the new Config that we'll return
            Config myNewConfig = (Config)obj;

            // We'll call the CreateKidDict now so that we already
            // have our Kid Dictionary ready to go.
            myNewConfig.CreateKidDict();

            return myNewConfig;
        }

Okay, we’re onto the next and final class before the Implementation stage. There really only needs to be two things pointed out in this class, so I’m just going to show them and not the whole class.

Take a look and you’ll notice that we’re creating XmlElement‘s.

This way both Name and Age are stored for each Kid in our XML config.

    public class Kid
    {
        [XmlElement("Name")]
        private String name;
        [XmlElement("Age")]
        private int age;

Implementation

    class Program
    {
        static void Main(string[] args)
        {
            // Create three new Kid()'s
            Kid jimmy = new Kid("Jimmy", 10);
            Kid kyle = new Kid("Kyle", 13);
            Kid sarah = new Kid("Sarah", 16);

            // Create an instance of our Config()
            Config outConfig = new Config();

            // Add each Kid() to the Config()
            outConfig.AddKid(jimmy);
            outConfig.AddKid(kyle);
            outConfig.AddKid(sarah);

            // Serialize our Config() and output it to an XML file
            outConfig.SerializeToXML(@"C:test-kids.xml");

            // Open up an XML file and Deserialize it into our Config()
            Config inConfig = new Config().DeserializeFromXML(@"C:test-kids.xml");

            // Loop through all the Kid()'s
            for (int i = 0; i < inConfig._kids.Count; i++)
            {
                Kid kid = inConfig._kids[i] as Kid;
                Console.WriteLine("Kid " + i + ": " + kid.Name);
            }

            Console.WriteLine("nUse GetKid() to get Kid()'s age: ");

            // Use GetKid() to find a kid and then call Age() to get the Kid()'s age
            Console.WriteLine("Jimmy is " + inConfig.GetKid("Jimmy").Age.ToString() + " years old.");
            Console.WriteLine("Kyle is " + inConfig.GetKid("Kyle").Age.ToString() + " years old.");
            Console.WriteLine("Sarah is  " + inConfig.GetKid("Sarah").Age.ToString() + " years old.");

            // Pause and wait for us to hit return, so that we can read the output
            Console.ReadLine();
        }
    }

I’m going to briefly go over this class as anyone who has been programming for any significant amount of time should know how to make method calls on classes, etc.

  1. We create three new Kid()‘s.
  2. We create our Config() instance to be used for output.
  3. We add all three Kid()‘s to our Config().
  4. Finally, we output our Config() using our SerializeToXML() method.
            // Create three new Kid()'s
            Kid jimmy = new Kid("Jimmy", 10);
            Kid kyle = new Kid("Kyle", 13);
            Kid sarah = new Kid("Sarah", 16);

            // Create an instance of our Config()
            Config outConfig = new Config();

            // Add each Kid() to the Config()
            outConfig.AddKid(jimmy);
            outConfig.AddKid(kyle);
            outConfig.AddKid(sarah);

            // Serialize our Config() and output it to an XML file
            outConfig.SerializeToXML(@"C:test-kids.xml");

Now, in a real circumstance(real life situation), we probably wouldn’t simply write out a config and then decide to immediately read it back in on the next line, but that’s what we’re going to do here since I’m simply trying to show each feature off that we have just created.

So, what we’re going to do is:

  1. De-serialize the Config() we just saved by calling our method DeserializeFromXML().
  2. Loop through all the Kid()‘s and print out their Name‘s to make sure we got them all.
  3. As a final test, get our GetKid() method to pull each Kid()‘s Age from our previously created Kid Dictionary.
            // Open up an XML file and Deserialize it into our Config()
            Config inConfig = new Config().DeserializeFromXML(@"C:test-kids.xml");

            // Loop through all the Kid()'s
            for (int i = 0; i < inConfig._kids.Count; i++)
            {
                Kid kid = inConfig._kids[i] as Kid;
                Console.WriteLine("Kid " + i + ": " + kid.Name);
            }

            Console.WriteLine("nUse GetKid() to get Kid()'s age: ");

            // Use GetKid() to find a kid and then call Age() to get the Kid()'s age
            Console.WriteLine("Jimmy is " + inConfig.GetKid("Jimmy").Age.ToString() + " years old.");
            Console.WriteLine("Kyle is " + inConfig.GetKid("Kyle").Age.ToString() + " years old.");
            Console.WriteLine("Sarah is  " + inConfig.GetKid("Sarah").Age.ToString() + " years old.");

Well, that’s all there is to it! Hope this all makes sense. If you have any trouble, simply download the source code provided at the top of this article and mess around with it. See what works and doesn’t work when you change things. That is honestly how I learn most tips and tricks, by tedious trial and error.

One last thing I’d like to mention is that I know there is probably an easier way(and more optimized) to do the whole Config() class structure, but this demonstration is for the purpose of simply learning the basics of XML Serialization. It can be taken much further than this, but that would be out of the scope I’m aiming for.

http://zyaga.com/wp-content/plugins/sociofluid/images/digg_48.png http://zyaga.com/wp-content/plugins/sociofluid/images/reddit_48.png http://zyaga.com/wp-content/plugins/sociofluid/images/google_48.png http://zyaga.com/wp-content/plugins/sociofluid/images/facebook_48.png

About Zyaga

I'm a Computer Programmer, though I have quite a lot of other hobbies and interests. You can usually find me studying Japanese, Blogging, watching Anime(for hours at a time), or possibly even practicing some Martial Arts. My brain runs rampant so I have to fuel it's fire by having many hobbies to switch back and forth from.

Leave a comment

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>