Saturday 24 August 2013

IXmlSerializable – Control XML Serialization

Sometimes we are in hard need to control the xml serialization. One of these needs could be to reduce the serialized data, so that less data will travel over wire and hence we will get the improved data transfer speed.

To control it, we can use the IXmlSerializable interface. This interface contains three functions

  1. XmlSchema GetSchema()
  2. void ReadXml(XmlReader reader)
  3. void WriteXml(XmlWriter writer)

In these functions, we can control the serialization with the help of XMLReader and XMLWriter. IXmlSerializable interface is recognized by the both XmlSerializer and Data Contract Serializer; and hence it can be used used by WCF and ASMX Web Services.

Lets have a look into the code - 

Code

using System;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Schema;
using System.Xml.Serialization;

namespace XMLSerialization
{
internal class Program
{
private static void Main(string[] args)
{
Person[] p = new Person[3];
p[0] = new Person() { Name = "Sanjay", Age = 30 };
p[1] = new Person() { Name = "Sanjay Legha", Age = 0 };
p[2] = new Person() { Age = 30 };

//Person p = new Person() { Name = "Sanjay", Age = 50 };

string filePath = @"D:\Sanjay\TempCode\XMLSerialization\XMLSerialization\bin\Debug\Serialized.xml";
using (System.IO.FileStream fs = new System.IO.FileStream(filePath, System.IO.FileMode.Create))
{
System.Xml.Serialization.XmlSerializer x = new System.Xml.Serialization.XmlSerializer(p.GetType());
x.Serialize(fs, p);
}

using (System.IO.FileStream fs = new System.IO.FileStream(filePath, System.IO.FileMode.Open))
{
System.Xml.Serialization.XmlSerializer x = new System.Xml.Serialization.XmlSerializer(p.GetType());
object obj = x.Deserialize(fs);
}

Console.Write("Done");
Console.Read();
}
}

public class Person : IXmlSerializable
{
public Person()
{
this.Name = string.Empty;
this.Age = 0;
}

[XmlElement(IsNullable = false)]
public string Name { get; set; }

[XmlElement()]
public int Age { get; set; }

public XmlSchema GetSchema()
{
return null;
}

public void ReadXml(XmlReader reader)
{
if (reader.NodeType == XmlNodeType.Element)
{
XElement el = XNode.ReadFrom(reader) as XElement;

foreach (var item in el.Nodes())
{
if (item is XElement)
{
XElement node = item as XElement;
switch (node.Name.LocalName)
{
case "Name":
this.Name = node.Value;
break;

case "Age":
this.Age = Convert.ToInt32(node.Value);
break;
}
}
}
}
}

public void WriteXml(XmlWriter writer)
{
if (!string.IsNullOrWhiteSpace(Name))
writer.WriteElementString("Name", Name);

if (Age != 0)
writer.WriteElementString("Age", Age.ToString());
}
}
}

Output

<?xml version="1.0"?>
<ArrayOfPerson xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Person>
    <Name>Sanjay</Name>
    <Age>30</Age>
  </Person>
  <Person>
    <Name>Sanjay Legha</Name>
  </Person>
  <Person>
    <Age>30</Age>
  </Person>
</ArrayOfPerson>

Generic Serialize Deserialize - XmlSerializer

 

A generic Xml Serializer De-Serializer code snap

public class SerializeDeserialize
{
    public static void SerializeData<T>(string filePath, T data)
    {
        using (System.IO.FileStream fs = new System.IO.FileStream(filePath, System.IO.FileMode.CreateNew))
        {
            System.Xml.Serialization.XmlSerializer x = new System.Xml.Serialization.XmlSerializer(data.GetType());
            x.Serialize(fs, data);
        }
    }

    public static T DeSerializeData<T>(string filePath)
    {
        T data;
        using (System.IO.FileStream fs = new System.IO.FileStream(filePath, System.IO.FileMode.Open, System.IO.FileAccess.Read))
        {
            System.Xml.Serialization.XmlSerializer x = new System.Xml.Serialization.XmlSerializer(typeof(T));
            object obj = x.Deserialize(fs);
            data = (T)obj;
        }

        return data;
    }
}