Serialization is the process of taking objects and converting their state information into a format (stream/file) that can be stored or transported. The basic idea of serialization is that an object writes its current state, usually indicated by the value of its member variables, to persistent storage. Later, the object can eventually be re-created by reading or deserializing the object's state from the storage (converting stream into an object).
The .NET Framework (1.1) features two serializing technologies:
- Binary serialization preserves type fidelity, which is useful for preserving the state of an object between different invocations of an application. For example, you can share an object between different applications by serializing it to the Clipboard. You can serialize an object to a stream, to a disk, to memory, over the network, and so forth. Remoting uses serialization to pass objects "by value" from one computer or application domain to another.
- XML serialization serializes only public properties and fields (XML serialization does not convert methods, indexers, private fields, or read-only properties) and does not preserve type fidelity. This is useful when you want to provide or consume data without restricting the application that uses the data. Because XML is an open standard, the XML stream can be processed by any application.
Sometimes you will have custom data objects in your application that you want to transfer to different other applications in different formats. Before
XSLT will come to the rescue you will have to make sure that your data objects can be serialized. In this example I've made use of
XML Serialization to serialize a custom data object.
A
PlayerCollection consists of a collection of
Players. Note the Serializable attribute of the two classes. It indicates that the two classes can be serialized.
using System;
namespace XMLTransformation
{
/// <summary>
/// Player
/// </summary>
[Serializable()]
public class Player
{
private string id;
private string firstName;
private string lastName;
private Teams team;
public Player() {}
public string Id
{
get { return this.id; }
set { this.id = value; }
}
public string FirstName
{
get { return this.firstName; }
set { this.firstName = value; }
}
public string LastName
{
get { return this.lastName; }
set { this.lastName = value; }
}
public Teams Team
{
get { return this.team; }
set { this.team = value; }
}
}
}
using System;
using System.Collections;
namespace XMLTransformation
{
/// <summary>
/// Collection of Players
/// </summary>
[Serializable()]
public class PlayerCollection : CollectionBase
{
public int Add(Player value)
{
int index = base.List.Add(value);
return (index);
}
public bool Contains(Player value)
{
bool b = base.List.Contains(value);
return (b);
}
public int IndexOf(Player value)
{
int index = base.List.IndexOf(value);
return (index);
}
public void Remove(Player value)
{
base.List.Remove(value);
}
public Player this[int index]
{
get { return (Player) base.InnerList[index]; }
}
}
}
When the collection is filled with players, it can be serialized, loaded into an XML-document and saved to file ...
private void btnSerialize_Click(object sender, System.EventArgs e)
{
//Create XmlSerializer to serialize object into XML document
XmlSerializer serializer = new XmlSerializer(typeof(PlayerCollection));
using(MemoryStream inputStream = new MemoryStream())
{
//Serialize playerCollection-object to inputStream
serializer.Serialize(inputStream, this.playerCollection);
inputStream.Seek(0, SeekOrigin.Begin);
//Load XML Document from Memory
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.Load(inputStream);
//Save XML to file
xmlDocument.Save(@"c:\SerializedCollection.xml");
}
}
The
MemoryStream class creates streams that have memory as a backing store instead of a disk or a network connection. MemoryStream encapsulates data stored as an unsigned byte array that is initialized upon creation of a MemoryStream object, or the array can be created as empty. The encapsulated data is directly accessible in memory. Memory streams can reduce the need for temporary buffers and files in an application. Storing data to memory instead of to disk will increase your performance. The current position of a stream is the position at which the next read or write operation could take place. The current position can be retrieved or set through the
Seek method. In the code, the position is set to the beginning of the stream before loading the XML Document.
The SerializedCollection.xml file will now serve as template for creating the XSLT that will transform the data in the appropriate way(s).
With XSLT I have the possibility to create for instance a new XML-file that will contain a sorted list of all players (see XML output a little but further).
When executing the transformation on the serialized XML, you will get ...
Now you can combine all this in C# : serialize XML, transform serialized XML with XSLT and put output in a string-variable that can be transmitted to any kind of procedure/application. All without writing temporary files to disk. Look also how easy it is (1 line of code) to get the outputString from the outputStream. No need to read bytes from the stream and convert them into a char-array and so on. The GetString() method of the UTF8-Encoding returns a string containing the decoded representation of a range of bytes in a byte array. I won't forget this "trick"!
MemoryStream outputStream = new MemoryStream();
XmlSerializer serializer = new XmlSerializer(typeof(PlayerCollection));
using(MemoryStream inputStream = new MemoryStream())
{
//Serialize object to inputStream
serializer.Serialize(inputStream, this.playerCollection);
inputStream.Seek(0, SeekOrigin.Begin);
//Create XPathDocument with inputStream
XPathDocument inputDoc = new XPathDocument(inputStream);
XmlResolver xmlUrlResolver = new XmlUrlResolver();
XslTransform xslTransform = new XslTransform();
//Load XSLT
xslTransform.Load(@"../../TransformFootball.xslt");
//Do Transformation [input = XPathDocument - output = MemoryStream]
xslTransform.Transform(inputDoc, null, outputStream, xmlUrlResolver);
}
string output = System.Text.Encoding.UTF8.GetString(outputStream.ToArray());