Introduction
My previous article XML Serialization and Deserialization (Part-1) , talk about serialization of object 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:
<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:public class Address
{
public int HouseNo { get; set; }
public string StreetName { get; set; }
public string City { get; set; }
}
This class contain variable name 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 lets see a basic program which will map this XML to the class object:
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
Following point should be noted while creating a class for Deserialization :- Class variable/property should always be declared as public
- We need to have Default/ Non Parameterised Constructor in order to deserialize.
deserializer.Deserialize(reader)
" have no provision to pass value to parameterised constructor.In the above code, we have simple XML Elements present with no sub Elements. Lets explore further and deal with some complicated situations where the XML Element may have further sub Tags:
Lets complicate the situation further and try to "deserialize" following "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: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 you 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:- Attribute of "
AddressDirectory
" tag if present - Its Childnodes example "Address" (can only access "Address tags", cannot drill down to child nodes of "Address" Tag)
-
InnerText
(if present)
AddressDirectory
cannot extract information about the child tags of "Address" and the "Address" tag attributes. In order to fetch info about the "ChildNodes" of "Address
" tag, we need to create another class that can store the attribute info and childnode info (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 list of class "Address" in "AddressDirectory
"
class so that multiple "Address" tag info 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:
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: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 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: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 store 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 while deserialization
Attributes that can be useful while deserialization are:XmlElement
XmlAttribute
-
XmlText
Observe the following 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:AddressDirectory
is the root node of the XML file-
AddressDirectory
contains an "XmlAttribute
" as "id
" containing value "1" - "
AddressDirectory
" contains "XmlElement
" likeDirectoryOwner
,Address
,Designation
,Address
- "Designation" tab contains an a "
XmlAttribute
" ("place") and an "XmlText
" ("Delhi")
XmlElement
", "XmlAttribute
", "XmlText
". While deserializing such complex XML where we can have all the three component we need to explicitly specify whether the class variable store "Element
", "Attribute
" or "XmlText
".Let's try to desterilize this XML:
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 it can fetch information about the childnodes
of Address
tag. Therefore in order to extract these info we need to
create another class for Address
and Designation
. Since we are having
multiple Address
tags therefore we are having 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.public class Address
{
[XmlAttribute("AddressId")]
public string AddressId { get; set; }
[XmlElement("HouseNo")]
public string HouseNo { get; set; }
[XmlElement("StreetName")]
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:
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. Example:[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.Source URL : http://www.codeproject.com
0 comments:
Post a Comment