Thursday, January 24, 2008

Xml Serialization

The Xml serialization is the most compatible and versatile serialization technique. We can set attributes for the class we want to serialize for produccing the output we want. Here an example:

Serializing:

// Building the object instance
Person p = new Person("Oscar", "L", new DateTime(1972, 6, 16));
 
// Now, the Person class includes a List named Friends
p.Friends.Add(new Person("John", "T", new DateTime(1970, 1, 25)));
p.Friends.Add(new Person("Mary", "Z", new DateTime(1975, 12, 1)));
 
// Our target file stream
FileStream fs = File.Create("c:\\filename.xml");
 
// The xml serializer
XmlSerializer xs = new XmlSerializer(typeof(Person));
 
// Serializing the person object
xs.Serialize(fs, p);
 
fs.Close();  // Don't forget to close the file stream
Deserializing:

// Our source file stream
FileStream fs = File.OpenRead("c:\\filename.xml");
 
// The xml serializer
XmlSerializer xs = new XmlSerializer(typeof(Person));
 
// Deserializing the object
Person p = (Person)xs.Deserialize(fs);
 
fs.Close();  // Don't forget to close the file stream
 
// Showing results
MessageBox.Show(p.FirstName + " " + p.Age.ToString());
MessageBox.Show("Number of friends: " + p.Friends.Count.ToString());
And here the Person class definition:

[XmlRoot(ElementName="thisPerson")]
public class Person
{
    [XmlElement(ElementName="Name")]
    public string FirstName;
    public string LastName;
 
    [XmlAttribute]
    public DateTime BirthDay;
 
    [XmlIgnore]
    public int Age;
 
    [XmlArray("myFriends")]
    [XmlArrayItem("myFriend")]
    public People Friends = new People();
 
    public Person()
    {
    }
 
    public Person(string _firstName, string _lastName, DateTime _birthDay)
    {
        FirstName = _firstName;
        LastName = _lastName;
        BirthDay = _birthDay;
 
        Age = DateTime.Now.Year - BirthDay.Year - 1;
    }
}
 
public class People : List<Person>
{
}
Notice how I named the root node as 'thisPerson' and the element FirstName as 'Name'. I also set the BirthDay for serializing as an XmlAttribute instead of an XmlElement. And I set the Age for ignoring it (XmlIgnore attribute) so it will not included into the output.

For the list named Friends, I apply the XmlArray attribute to named it as 'myFriends' and every item in the collection as 'myFriend'.

This will produce the following output:

<?xml version="1.0"?>
<thisPerson xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" BirthDay="1972-06-16T00:00:00">
  <Name>Oscar</Name>
  <LastName>L</LastName>
  <myFriends>
    <myFriend BirthDay="1970-01-25T00:00:00">
      <Name>John</Name>
      <LastName>T</LastName>
      <myFriends />
    </myFriend>
    <myFriend BirthDay="1975-12-01T00:00:00">
      <Name>Mary</Name>
      <LastName>Z</LastName>
      <myFriends />
    </myFriend>
  </myFriends>
</thisPerson>
If we want to control errors, we need to handle some events:

// Event handlers
xs.UnknownAttribute += new XmlAttributeEventHandler(xs_UnknownAttribute);
xs.UnknownElement += new XmlElementEventHandler(xs_UnknownElement);
xs.UnknownNode += new XmlNodeEventHandler(xs_UnknownNode);
xs.UnreferencedObject += new UnreferencedObjectEventHandler(xs_UnreferencedObject);
void xs_UnreferencedObject(object sender, UnreferencedObjectEventArgs e)
{
    // something happen
}
 
void xs_UnknownNode(object sender, XmlNodeEventArgs e)
{
    // something happen
}
 
void xs_UnknownElement(object sender, XmlElementEventArgs e)
{
    // something happen
}
 
void xs_UnknownAttribute(object sender, XmlAttributeEventArgs e)
{
    // something happen
}
Implementing the IXmlSerializable:

If we want more control over serialization, we need to implement the interface IXmlSerializable as bellow:

[XmlRoot(ElementName = "thisPerson")]
public class Person : IXmlSerializable
{
    public string FirstName;
    public string LastName;
    public DateTime BirthDay;
 
    public int Age;
 
    public People Friends = new People();
 
    public Person()
    {
    }
 
    public Person(string _firstName, string _lastName, DateTime _birthDay)
    {
        FirstName = _firstName;
        LastName = _lastName;
        BirthDay = _birthDay;
 
        Age = DateTime.Now.Year - BirthDay.Year - 1;
    }
 
    #region IXmlSerializable Members
 
    public System.Xml.Schema.XmlSchema GetSchema()
    {
        return (null);
    }
 
    public void ReadXml(System.Xml.XmlReader reader)
    {
        reader.MoveToContent();
 
        BirthDay = DateTime.Parse(reader.GetAttribute("BirthDay"));
 
        FirstName = reader.ReadElementString();
        LastName = reader.ReadElementString();
        Age = int.Parse(reader.ReadElementString());
 
        // Reading friends collection
        Friends.Clear();
 
        int depth = reader.Depth;  // actual depth
        bool read = reader.Read(); // next read
        while ((read) && (reader.Depth > depth))
        {
            reader.MoveToContent(); 
 
            if (reader.IsStartElement())
            {
                Person p = new Person();
                p.ReadXml(reader);
                Friends.Add(p);
            }
 
            read = reader.Read();
        }
    }
 
    public void WriteXml(System.Xml.XmlWriter writer)
    {
        writer.WriteAttributeString("BirthDay", BirthDay.ToString());
        writer.WriteElementString("Name", FirstName);
        writer.WriteElementString("LastName", LastName);
        writer.WriteElementString("Age", Age.ToString());
 
        writer.WriteStartElement("myFriends");
        foreach (Person p in Friends)
        {
            writer.WriteStartElement("myFriend");
            p.WriteXml(writer);
            writer.WriteEndElement();
        }
        writer.WriteEndElement();
    }
 
    #endregion
}    
 
public class People : List<Person>
{
}
And here the output it produces:

<?xml version="1.0"?>
<thisPerson BirthDay="6/16/1972 12:00:00 AM">
  <Name>Oscar</Name>
  <LastName>L</LastName>
  <Age>35</Age>
  <myFriends>
    <myFriend BirthDay="1/25/1970 12:00:00 AM">
      <Name>John</Name>
      <LastName>T</LastName>
      <Age>37</Age>
      <myFriends />
    </myFriend>
    <myFriend BirthDay="12/1/1975 12:00:00 AM">
      <Name>Mary</Name>
      <LastName>Z</LastName>
      <Age>32</Age>
      <myFriends />
    </myFriend>
  </myFriends>
</thisPerson>

1 comments:

Anesha said...

Hi Nice Blog .Data processing services are helpful in streamlining a wide range of corporate activities and operations. Data processing and related other services are not only good to present the full and processed data that is to be used for the overall benefit rather their primary function is to present an insightful explanation of the data. XML Conversion


View My Stats