Click here to Skip to main content
15,861,125 members
Articles / Programming Languages / C# 3.5

XML Serialization and Deserialization: Part 2

Rate me:
Please Sign up or sign in to vote.
4.93/5 (77 votes)
13 Oct 2018CPOL6 min read 286.6K   119   35
Serialization and deserialization of XML

Introduction

My previous article XML Serialization and Deserialization (Part-1) talks about serialization of objects to XML form. In this article, we will discuss about "Deserialization of XML" back to object form. Deserialization is used to convert bytes of data, such as XML or binary data, to "Object" type. An XML file can be reconverted back to an Object using deserialization.

Let's start with the basic example. Here is the XML file that need to be deserialized:

XML
<AddressDetails>
  <HouseNo>4</HouseNo>
  <StreetName>Rohini</StreetName>
  <City>Delhi</City>
</AddressDetails>

So in order to deserialize this XML file, we need to create a class:

C#
public class Address
{
    public int HouseNo { get; set; }
    public string StreetName { get; set; }
    public string City { get; set; }
}

This class contains a variable name which is the same as that of XML tags, XML tag values by default get mapped to the corresponding variable in the class. "HouseNo" in class "Address" will be automatically mapped to XML tag "HouseNo".

Now let's see a basic program which will map this XML to the class object:

C#
public static void Main(string[] args)
{
    XmlSerializer deserializer = new XmlSerializer(typeof(Address));
    TextReader reader = new StreamReader(@"D:\myXml.xml");
    object obj = deserializer.Deserialize(reader);
    Address XmlData = (Address)obj;
    reader.Close();
}

"deserializer.Deserialize" function is used to deserialize the XML data which is there in XML file. Now since we have deserialized the XML file structure to object form, we can now access the XML tag values:

Address.HouseNo
Address.StreetName
Address.City

The following points should be noted while creating a class for Deserialization:

  1. Class variable/property should always be declared as public
  2. We need to have Default/ Non Parameterised constructor in order to deserialize

Any class without "Default/ Non Parameterised" constructor will result into an error since "deserializer.Deserialize(reader)" has no provision to pass value to parameterised constructor.

In the above code, we have simple XML Elements present with no sub Elements. Let's explore further and deal with some complicated situations where the XML Element may have further sub Tags:

Let's complicate the situation further and try to "deserialize" the following "XML":

XML
<?xml version="1.0"?>
<AddressDirectory>
  <Address>
    <HouseNo>1</HouseNo>
    <StreetName>Pitampura</StreetName>
    <City>Delhi</City>
  </Address>
  <Address>
    <HouseNo>4</HouseNo>
    <StreetName>Rohini</StreetName>
    <City>Delhi</City>
  </Address>
</AddressDirectory>

Let's see the difference over here. In the following XML, we have multiple "Address" tags. And also the Address tag contains further sub Tags. Therefore, we need to create our class such that it can hold multiple "Address" tags and its sub tags. Let's see how we can create the class:

C#
public class AddressDirectory
{
    [XmlElement("Address")] 
    public List<Address> addressList = new List<Address>(); 
}
public class Address
{
    public int HouseNo { get; set; }
    public string StreetName { get; set; }
    public string City { get; set; }
}

Remember here that when we create a class for deserialization of any tag, We can only drill down to a single level. To explain this in simple words, let me take an example. In the above XML, we have "AddressDirectory" tab. In order to Deserialize, we create a class for "AddressDirectory" tag. Now this class can have the details of following for "AddressDirectory" XML tag:

  1. Attribute of "AddressDirectory" tag if present
  2. Its Childnodes example "Address" (can only access "Address tags", cannot drill down to child nodes of "Address" Tag)
  3. InnerText (if present)

The class AddressDirectory cannot extract information about the child tags of "Address" and the "Address" tag attributes. In order to fetch information about the "ChildNodes" of "Address" tag, we need to create another class that can store the attribute information and childnode information (up to first level).

Over here, we have created a class AddressDirectory that maps to the root tag element of "XML". And the root tag further contains "Address" tags. We can have multiple tags for "Address" over here, therefore we have created a list of class "Address" in "AddressDirectory" class so that multiple "Address" tag information can be stored. Here, in the class, we can see XmlElement written over addressList. This attribute is used since the name of the class variable is different from that in XML file therefore in order to map the class variable with the XML tag, we use the keyword XmlElement. We will discuss about this later in the article.

We will see more examples about this further in the article.

The program to be executed in order to deserialize the XML will be:

C#
XmlSerializer deserializer = new XmlSerializer(typeof(AddressDirectory));
TextReader reader = new StreamReader(@"D:\myXml.xml");
object obj = deserializer.Deserialize(reader);
AddressDirectory XmlData = (AddressDirectory)obj;
reader.Close();

The resultant object "XmlData" will contain a list of object of type "Address". We can access the data for the first Address tag as:

C#
XmlData.addressList[0].HouseNo;
XmlData.addressList[0].StreetName; 
XmlData.addressList[0].City;

The XML can be further complicated, let's see the following XML file structure and its class representation:

XML
<?xml version="1.0"?>
<AddressDirectory>
  <Owner>Mayank</Owner>
  <Age>24</Age>
  <Company>BIPL</Company>
  <Address>
    <HouseNo>1</HouseNo>
    <StreetName>Pitampura</StreetName>
    <City>Delhi</City>
  </Address>
  <Address>
    <HouseNo>4</HouseNo>
    <StreetName>Rohini</StreetName>
    <City>Delhi</City>
  </Address>
</AddressDirectory>

Here, we can see some additional tags inside the "AddressDirectory" like "Owner", "Age", "Company" along with the list of "Address" tags. So the class structure for the XML would be:

C#
public class AddressDirectory
{
    public string Owner { get; set; }
    public string Age { get; set; }
    public string Company { get; set; }
    [XmlElement("Address")]
    public List<Address> addressList = new List<Address>(); 
}

public class Address
{
    public string HouseNo { get; set; }
    public string StreetName { get; set; }
    public string City { get; set; }
}

The childnodes of "AddressDirectory" tags are present inside the AddressDirectory class and the childnodes of Address tab are present inside the address class.

Note: What is important to observe here is that the class can contain only those "tag values" which are their immediate childnodes, i.e., AddressDirectory can only contain the information about their immediate childnode like "Owner", "Company", "Age" and "Address". But here, "Address" is further containing more tags. The childnodes for "Address" tag cannot be represented by the class "AddresssDirectory". Therefore, we require another class for "Address" tag that stores the childnode information about "Address" class. The "Address" class will further contain the value of their immediate childnode "HouseNo", "StreetName", "City". Since we have multiple Address tags, therefore we have a "List" of "Address" class.

XML Attributes during Deserialization

Attributes that can be useful during deserialization are:

  1. XmlElement
  2. XmlAttribute
  3. XmlText

These three attributes provide mapping information. It provides information about which element of the XML tag will be mapped to which variable of the class.

Observe the following XML:

XML
<?xml version="1.0" encoding="utf-8" ?>
<AddressDirectory id="1">
  <DirectoryOwner>Mayank</DirectoryOwner>
  <PinCode>110085</PinCode>
  <Designation place="Delhi">Engineer</Designation>
  <Address AddressId="12">
    <HouseNo>4</HouseNo>
    <StreetName>Rohini</StreetName>
    <City>Delhi</City>  
  </Address>
  <Address AddressId="13">
    <HouseNo>4</HouseNo>
    <StreetName>Rohini</StreetName>
    <City>Delhi</City>
  </Address>
</AddressDirectory>

Let's observe the different components of this XML file:

  1. AddressDirectory is the root node of the XML file
  2. AddressDirectory contains an "XmlAttribute" as "id" containing value "1"
  3. "AddressDirectory" contains "XmlElement" like DirectoryOwner, Address, Designation, Address
  4. "Designation" tab contains an a "XmlAttribute" ("place") and an "XmlText" ("Delhi")

So from the above XML, we can figure out what are "XmlElement", "XmlAttribute", "XmlText". While deserializing such complex XML where we can have all the three components, we need to explicitly specify whether the class variable stores "Element", "Attribute" or "XmlText".

Let's try to desterilize this XML:

C#
public class AddressDirectory
{
    [XmlElement("DirectoryOwner")]
    public string DirectoryOwner { get; set; }
    [XmlElement("PinCode")]
    public string PinCode { get; set; }
    [XmlElement("Address")]
    public List<Address> Address { get; set; }
    [XmlElement("Designation")]
    public Designation designation { get; set; }
} 

Here, we have mapped the class variable DirectoryOwner to DirectoryOwner tag of XML file.

Observe here that the class AddressDirectory contains the child node of the AddressAttribute tag. It drills down to the first level only, i.e., it cannot retrieve values about the Attribute of Designation and neither can it fetch information about the childnodes of Address tag. Therefore, in order to extract these information, we need to create another class for Address and Designation. Since we have multiple Address tags, we have a list of Address class in AddressDirectory.

Let's explore the Address class and the Designation class:

public class Designation
{
    [XmlAttribute("place")]
    public string place { get; set; }
    [XmlText]
    public string JobType { get; set; }
}

The Designation class here contains two variables, one for storing the innerText and other for storing the place attribute for the Designation tags.

C#
public class Addresse
{
    [XmlAttribute("AddressId")]
    public string AddressId { get; set; }
    [XmlElement("HouseNo")]
    public string HouseNo { get; set; }
    [XmlElement("StreetName")]e
    public string StreetName { get; set; }
    [XmlElement("City")]
    public string City { get; set; }
}

The Address class further contains a variable that can store the attributes and child node details of Address tags.

The program to be executed in order to deserialize the XML will be:

C#
XmlSerializer deserializer = new XmlSerializer(typeof(AddressDirectory));
TextReader reader = new StreamReader(@"D:\myXml.xml");
object obj = deserializer.Deserialize(reader);
AddressDirectory XmlData = (AddressDirectory)obj;
reader.Close();

One more thing that needs to be kept in mind is that, the keywords XmlElement, XmlAttribute, and XmlText are used to map information inside the XML tag to the class variable. The class variable name can be different from that in XML. For example:

C#
[XmlElement("HouseNo")]
public string Number { get; set; }

Here, we can see that the XML element HouseNo will be mapped to the class variable Number.

Conclusion

Deserialization and serialization is a very efficient way to convert the object to XML and vice versa. This save lots of saving time and effort.

License

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



Comments and Discussions

 
QuestionThe deserializer encounters a tag for which there is no property in which to put the data Pin
Member 120616988-Feb-19 5:43
Member 120616988-Feb-19 5:43 
Questionpossible misprints, lack of editing, Pin
Member 120616987-Feb-19 10:59
Member 120616987-Feb-19 10:59 
PraiseGreat article Pin
shwetavc3015-Nov-18 20:29
shwetavc3015-Nov-18 20:29 
GeneralMy vote of 5 Pin
Karthik_Mahalingam13-Mar-17 23:35
professionalKarthik_Mahalingam13-Mar-17 23:35 
QuestionNice and simple explaination Pin
tusharthechamp23-Dec-16 19:14
tusharthechamp23-Dec-16 19:14 
QuestionNice explanation Pin
phil.o31-Oct-15 5:07
professionalphil.o31-Oct-15 5:07 
QuestionThanks Pin
Sohaib Javed18-Oct-15 13:20
Sohaib Javed18-Oct-15 13:20 
QuestionSample project would have be nice Pin
fredatcodeproject16-Sep-15 5:44
professionalfredatcodeproject16-Sep-15 5:44 
AnswerRe: Sample project would have be nice Pin
fredatcodeproject23-Sep-15 3:49
professionalfredatcodeproject23-Sep-15 3:49 
GeneralRe: Sample project would have be nice Pin
phil.o31-Oct-15 5:02
professionalphil.o31-Oct-15 5:02 
GeneralRe: Sample project would have be nice Pin
fredatcodeproject4-Nov-15 1:36
professionalfredatcodeproject4-Nov-15 1:36 
QuestionUnderstanding Pin
sugumarPalanichamy31-May-15 21:52
sugumarPalanichamy31-May-15 21:52 
QuestionAbout Deserialization Pin
Member 116478222-May-15 4:04
Member 116478222-May-15 4:04 
QuestionXML De serializing Pin
Balasubramanya Bharadwaj22-Jan-15 19:48
Balasubramanya Bharadwaj22-Jan-15 19:48 
AnswerRe: XML De serializing Pin
Member 116478222-May-15 4:15
Member 116478222-May-15 4:15 
GeneralEase of understanding Pin
K K Srinivasan2-Jan-15 7:06
K K Srinivasan2-Jan-15 7:06 
Questiongetting an error when accessing list: Index was out of range. Must be non-negative and less than the size of the collection. Pin
Member 1130745512-Dec-14 20:08
Member 1130745512-Dec-14 20:08 
General5 star article Pin
Amit Dhakre10-Dec-14 20:54
Amit Dhakre10-Dec-14 20:54 
QuestionVERY NICELY PUT.... Pin
IamPervaze7-Aug-14 20:19
IamPervaze7-Aug-14 20:19 
GeneralNicely articulated any very Usefull Pin
shivu0075-Aug-14 2:34
shivu0075-Aug-14 2:34 
GeneralMy vote of 5 Pin
Maciej Los17-Jun-14 7:41
mveMaciej Los17-Jun-14 7:41 
QuestionUse property or field Pin
heiyanquan31-Mar-14 16:01
heiyanquan31-Mar-14 16:01 
AnswerRe: Use property or field Pin
Maciej Los17-Jun-14 7:45
mveMaciej Los17-Jun-14 7:45 
GeneralMy vote of 1 Pin
shankarshan74-Mar-14 21:56
shankarshan74-Mar-14 21:56 
QuestionRe: My vote of 1 Pin
Maciej Los17-Jun-14 6:52
mveMaciej Los17-Jun-14 6:52 

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

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