您的位置:首页 > 其它

XML Serialization and Deserialization

2012-10-31 10:39 543 查看
原帖地址:http://www.codeproject.com/Articles/483055/XML-Serialization-and-Deserialization

这是一篇写得很不错的介绍XML序列化的文章,不过很少涉及反序列化,虽然标题里面有反序列化这几个字。

The article talks about Serialization of object in XML Format and Deserialization of XML file back to object. Serialization is a process by which object's state is transformed in some serial data format, such as XML or binary format. Deserialization
on the other hand is used to convert the byte of data, such as XML or binary data to object type. Serialization is the process of converting an object into a form that can be readily transported. For example, you can serialize an object and transport it over
the Internet using HTTP between a client and a server. On the other end, Deserialization reconstructs the object from the stream.XML serialization results in strongly typed classes with public properties and fields that are converted to a serial format (in
this case, XML) for storage or transport.
Let's start with a basic example. Here is a simple class the need to be Serialized :
public class AddressDetails
{
public int HouseNo { get; set; }
public string StreetName { get; set; }
public string City { get; set; }
private string PoAddress { get; set; }
}

Following point should be noted while creating a class for serialization :

XML serialization only serialize the public fields and properties.

XML Serialization do not include any type information.

We need to have Default/ Non Parameterised Constructor in order to serialize an Object.

ReadOnly properties are not Serialized.

Code to Serialize the above Class :
public static void Main(string[] args)
{
AddressDetails details = new AddressDetails();
details.HouseNo = 4;
details.StreeName = "Rohini";
details.City = "Delhi";
Serialize(details);
}
static public void Serialize(AddressDetails details)
{
XmlSerializer serializer = new XmlSerializer(typeof(AddressDetails));
using (TextWriter writer = new StreamWriter(@"C:\Xml.xml"))
{
serializer.Serialize(writer, details);
}
}

XmlSerializer (located in System.Xml.Serialization namespace) class is used to Serialize and Deserialize. The Class method "Serialize" is called. Since we have
to serialize in a file therefore we are creating "TextWriter". Since "TextWriter" impements "IDisposable",
therefore we have used "using" so that we need not to close the writer.
The output after the Serialization is :
<?xml version="1.0" encoding="utf-8"?>
<AddressDetails>
<HouseNo>4</HouseNo>
<StreetName>Rohini</StreetName>
<City>Delhi</City>
</AddressDetails>

Here in the Xml we can see that the Head tag of the XML created is same as that of the Class name and the subtag names are same as the properties in class "AddressDetails". Each public property is displayed in form of Tags in the XML Created. We
can observe here that only public fields are displayed here.

XML Serialization and Attributes :

Some common Attributes that are available while Serialization are:

XmlAttribute : This member will be serialized as an XML attribute

XmlElement : The field will be serialized as an XML element

XmlIgnore : Field will be ignored while Serialization

XmlRoot : Represent XML document's root Element

<Details id ="File">
<Name>Mayank</Name>
<Company>ABC</Company>
</Details>

Here in this Xml file, we can see that "id" is the attribute for an XML Tag "Details" and "Name/ Address" are the Elements of the XML File.

Use of XmlElement:

Further if we need to have different Tag name in Xml from the Class property Name. We can introduce the "XmlElement" Attribute to it in the class structure.
public class AddressDetails
{
[XmlElement("Number")]
public int HouseNo { get; set; }
[XmlElement("Street")]
public  string StreetName { get; set; }
[XmlElement("CityName")]
}

"[XmlElement("Number")]" specifies that the property "HouseNo" will be serialized with the Tag name "Number"
in the Xml File. It help us to map between the XML Tag name and the class Property Name. The resultant XML string with the Custom tag name is given below :
<AddressDetails>
<Number>4</Number>
<Street>Rohini</Street>
<CityName>Delhi</CityName>
</AddressDetails>

Use of XmlAttribute :

If we want that the property "HouseNo" should occur as the attribute for the Tag " AddressDetails"
then we should use "XmlAttribute". XmlAttribute serialize the object property as the attribute for the parent tag. Following Code illustrates the functionality :
public class AddresssDetails
{
[XmlAttribute]("Number")]
public int HouseNo { get; set; }
[XmlElement("Street")]
public  string StreetName { get; set; }
[XmlElement("CityName")]
public string City {get; set;}
}

The XML serialized output for the code will be :
<AddressDetails Number="4">
<Street>Rohini</Street>
<CityName>Delhi</CityName>
</AddressDetails>

Notice here, Since the class property "HouseNo" is specified as "XMLAttribute" therefore this property is an Attribute for
the parent tag "AddressDetails".

Use to XmlIgnore:

By default, all public fields and public read/write properties are serialized by the XmlSerializer .
That is, the value of each public field or property is persisted as an XML element or XML attribute in an XML-document instance. In order to override this property apply "XmlIgnore" attribute to
it. This will remove the element from the XML. The code below explains the following:
public class AddressDetails
{
[XmlElement("Number")]
public int HouseNo;
[XmlElement("Street")]
public string StreetName;
[XmlIgnore]
public string City;
}

Here we can see that the property "City" contains "XmlIgnore" attribute. The resultant Xml created wont contain the "City" tag in it.
<AddressDetails>
<Number>4</Number>
<Street>ABC</Street>
</AddressDetails>

Notice here that the property "City" is not Serialized because of the attribute "XmlIgnore" placed on it.

Use of XmlRoot:

Every Xml has a root element. By default the name of the root element is same as the name of the class that is serialized. In order to give a custom name to the root element of
XML, we use XmlRoot Attribute. Implementation of this attribute is provided below:
[XmlRoot("Root")]
public class AddressDetails
{
[XmlElement("Number")]
public int HouseNo;
[XmlElement("Street")]
public string StreetName;
[XmlElement("CityName")]
public string City;
}

Here we can see that the Attribute "XmlRoot" is placed over "AddressDetails" class. This will now override the default serialization behavior which takes xml tag root name same as the
class name. The Xml will now have "Root" as the root tag.
<Root>
<HouseNo>4</HouseNo>
<StreetName>Rohini</StreetName>
<City>Delhi</City>
</Root>

Notice here that the root tag here is now "Root" and not the Class name.

Object List Serialization

Now let's try to serialize a list of AddressDetails object to XML File:
public static void Main(string[] args)
{
List<AddressDetails> AddressList = new List<AddressDetails>();
AddressDetails detail1 = new AddressDetails();
detail1.HouseNo ="4";
detail1.StreetName = "ABC";
detail1.City = "Delhi";

AddressDetails detail2 = new AddressDetails();
detail2.HouseNo ="3";
detail2.StreetName = "ABCD";
detail2.City = "New Delhi";

AddressList.Add(detail1);
AddressList.Add(detail2);
Serialize(AddressList);
}
public void Serialize(List<AddressDetails> list)
{
XmlSerializer serializer = new XmlSerializer(typeof(List<AddressDetails>));
using ( TextWriter writer = new StreamWriter( @"C:\Xml.txt")
{
serializer.Serialize(writer, list) 
}
}

The XML output for the above Execution will be :
<ArrayOfAddressDetails>
<AddressDetails>
<Number>4</Number>
<Street>ABC</Street>
<CityName>Delhi</CityName>
</AddressDetails>
<AddressDetails>
<Number>3</Number>
<Street>ABCD</Street>
<CityName>New Delhi</CityName>
</AddressDetails>
</ArrayOfAddressDetails>

Notice that the XML produced gives a list of AddressDetails object.

Serialization of classes containing other class Objects:

If we have a class structure such that a class contains an object of other class and we want to include that class object also for Serialization. Let's see the following Example :
public class PersonalDetails
{
public string Name { get; set; }
public int Age { get; set; }
public Address address;
}
public class Address
{
public int HouseNo { get; set; }
public string StreetName { get; set; }
public string City { get; set; }
}

This is how the PersonalDetails class will be serialized:
<PersonalDetails>
<Name>Mayank</Name>
<Age>24</Age>
<Address>
<HouseNo>4</HouseNo>
<StreetName>Rohini</StreetName>
<City>Delhi</City>
</Address>
</PersonalDetails>

To add more complexity to it lets try creating the following XML Structure :
<PersonalDetails>
<Name>Mayank</Name>
<Age>24</Age>
<Address HouseNo="4">
<StreetName>Rohini</StreetName>
<City>Delhi</City>
</Address>
</PersonalDetails>

Observe that the Difference over here is that we need to have "HouseNo" as the attribute for the Address Tag. Lets see what change will be made in class in order to create this structure:
public class PersonalDetails
{
public string Name { get; set; }
public int Age { get; set; }
public Address address;
public PersonalDetails()
{
Name = "Mayank";
Age = 24;
address = new Address();
}

}
public class Address
{
[XmlAttribute("HouseNo")]
public int HouseNo { get; set; }
public string StreetName { get; set; }
public string City { get; set; }
public Address()
{
HouseNo = 8;
StreetName = "Rohini";
City = "Delhi";
}
}

As per the requirement we wanted to have "HouseNo" as Xml Attribute instead of the normal XMLElement. Therefore we introduce "XmlAttribute" on property.
Let's try creating the following XML Structure:
<PersonalDetails>
<Name>Mayank</Name>
<Age>24</Age>
<address HouseNo="8">Rohini</address>
</PersonalDetails>

The difference over here is that we require the StreetName as innertext of the XML node "address". So in order to create such structure we have another attribute
"XmlText". This help us to add the particular property as innertext for a tag.
So the Code for creating such a structure is :
public class PersonalDetails
{
public string Name { get; set; }
public int Age { get; set; }
public Address address;
}
public class Address
{
[XmlAttribute("HouseNo")]
public int HouseNo { get; set; }
[XmlText]
public string StreetName { get; set; }
}

"XmlText" attribute here adds StreetName as InnerText to the tag "address"

Conclusion:

Serialization is a very efficient way to convert the object to XML. This save lots of saving time and effort.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: