Click here to Skip to main content
Licence CPOL
First Posted 4 Mar 2008
Views 14,007
Downloads 194
Bookmarked 21 times

XML Serialization for Complex Object Model

By | 5 Mar 2008 | Article
Handles object graphs and circular references in XML serialization

Introduction

About 3 months ago, I was asked to work out a program running on Pocket PC with .NET Compact Framework. It is a program drawing rooms and calculating the geometrical parameters and exporting them to an XML file. The program itself should be able to save the rooms to files and load from them.

Compact FrameWork 2.0 doesn't provide Binary Serialization. And XML Serialization is just too simple to handle what I need: I have to deal with a complex topology of object model. Room A may be associated to Room B, and Room B to Room C, Room C to Room A, it makes a circle finally, just like this:

DrawTools2005Xmlable

So, I need a way to serialize such an object model to XML. Fortunately, I had worked out something in my spare time. I call it "xmlable", just like "Serializable" in Binary Serialization.

Using the Code

I will introduce Alex Fr's DrawTools to show you how this has been done.

First, include IXmlabe.cs and Xmlable.cs to your project.

Derive the classes you want to serialize from interface IXmlable, and declare an attribute Xmlable for it, and implement two methods of IXmlable: FromXml and ToXml.

using Xmlable;
using System.Xml;

namespace DrawTools
{
    [Xmlable("DrawObject", IsUnique = false)] 
    abstract class DrawObject : IXmlable
    {
        public DrawObject(){/*...*/} // Xmlable need a constructor without parameter.

        public virtual void FromXml(XmlElement xmlEle, IXmlContext cnt)
        {
            //base.FromXml(xmlEle,cnt); 
            //the derived classes should call parent class's FromXml
            color = Color.Black;
            try { color = Color.FromArgb(Int32.Parse(xmlEle.GetAttribute("color"))); }
            catch (Exception) { }
            penWidth = 1;
            try { penWidth = Int32.Parse(xmlEle.GetAttribute("penWidth")); }
            catch (Exception) { }
            name = xmlEle.GetAttribute("name");

            XmlElement assoEle = xmlEle["associate"];
            if(null != assoEle)
            {
                objAsso = cnt.FromXml(assoEle.FirstChild as XmlElement) as DrawObject;
            }
        }
        public virtual void ToXml(XmlElement xmlEle, IXmlContext cnt)
        {
            //base.ToXml(xmlEle,cnt); 
            //the derived classes should call parent class's ToXml
            XmlToolkit.SetAttribute(xmlEle, "color", color.ToArgb().ToString());
            XmlToolkit.SetAttribute(xmlEle, "penWidth", penWidth.ToString());
            XmlToolkit.SetAttribute(xmlEle, "name", name);
            XmlElement assoEle = cnt.Document.CreateElement("associate");
            XmlElement objEle = cnt.ToXml(objAsso);
            if (null != objEle)
                assoEle.AppendChild(objEle);
            xmlEle.AppendChild(assoEle);
        } 
} 

[Xmlable("TagName", IsUnique = true)]<br />public class ClassA 
means that TagName will be the tag name of the XML nodes of the ClassA, and IsUnique = true means whatever amount of references of a same object of type ClassA is serialized into an XML file when the file is loaded, there would not be a lot of references to a lot of different objects.

In order to make DrawTools "Xmlable", the five classes : DrawObject, DrawLine, DrawPolygon, DrawRectangle, DrawEllipse and GraphicsList were modified.

GraphicsList is the container which contains DrawObject, its implementation of IXmlable is as follows:

public virtual void FromXml(XmlElement xmlEle, IXmlContext cnt)
{
    graphicsList.Clear();
    foreach (XmlElement objEle in xmlEle)
    {
        DrawObject obj = cnt.FromXml(objEle) as DrawObject;
        System.Diagnostics.Debug.Assert(null != obj);
        if (null != obj)
        {
            graphicsList.Add(obj);
        }
    }
}

public virtual void ToXml(XmlElement xmlEle, IXmlContext cnt)
{
    foreach (DrawObject obj in graphicsList)
    {
        XmlElement objEle = cnt.ToXml(obj);
        if (null != objEle)
            xmlEle.AppendChild(objEle);
    }
}

To save the document of DrawTools, just add some code in MainForm, like this:

Save

private void saveAsXMLToolStripMenuItem_Click(object sender, EventArgs e)
{
    if (dlgSave.ShowDialog() != DialogResult.OK)
        return ;

    XmlDocument doc = new XmlDocument();
    IXmlFormatter formatter = FepXmlableFactory.CreateXmlFormatter();
    IXmlContext cnt = FepXmlableFactory.CreateXmlContext(formatter, doc);

    XmlElement ele = cnt.ToXml(this.drawArea.GraphicsList);
    doc.AppendChild(ele);

    XmlDeclaration xmldecl;
    xmldecl = doc.CreateXmlDeclaration("1.0", null, null);
    doc.InsertBefore(xmldecl, doc.DocumentElement);

    doc.Save(dlgSave.FileName);
}

Load

private void loadFromXMLToolStripMenuItem_Click(object sender, EventArgs e)
{
    if (dlgOpen.ShowDialog() != DialogResult.OK)
        return;

    XmlDocument doc = new XmlDocument();
    doc.Load(dlgOpen.FileName);

    IXmlFormatter formatter = FepXmlableFactory.CreateXmlFormatter();
    IXmlContext cnt = FepXmlableFactory.CreateXmlContext(formatter, doc);

    GraphicsList graphList = cnt.FromXml(doc.DocumentElement) as GraphicsList;
    if(null == graphList)
        throw new System.IO.IOException(dlgOpen.FileName + " is not a valid file.");
    this.drawArea.GraphicsList = graphList;

    this.drawArea.Invalidate();
}

Hope This Will Help...

If you are confused by what I have written above, just download the project, run it, draw something, right click on it, set its properties and make them associate with each other. Go to menu "File->Save As XML","File->Load From XML", and open the saved file with text editors to have a look.

I haven't done much testing after I add Xmlable to DrawTools. Let's just focus on how objects are serialized to XML.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

brent.wjh

Software Developer (Senior)
YinhooTech
China China

Member

Live in Amoy China.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
GeneralMy vote of 5 Pinmembermanoj kumar choubey20:29 20 Feb '12  

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Mobile
Web03 | 2.5.120517.1 | Last Updated 6 Mar 2008
Article Copyright 2008 by brent.wjh
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid