XML Serialization


The simplest way to demonstrate Visual Basic’s support for XML is not with a complicated technology, such as SQL Server or ADO.NET, but with a practical use of XML, serializing a class.

The serialization of an object means that it is written out to a stream, such as a file or a socket (this is also known as dehydrating an object). The reverse process can also be performed: An object can be deserialized (or rehydrated) by reading it from a stream.

Tip 

The type of serialization described in this chapter is XML serialization, where XML is used to represent a class in serialized form.

To help you understand XML serialization, let’s examine a class named FilmOrder (which can be found in the code download from www.wrox.com). This class is implemented in Visual Basic and is used by the company for processing an order for movies. The class could be instantiated on a firm’s PDA, laptop, or even mobile phone (as long as the .NET Framework were installed).

An instance of FilmOrder corresponding to each order could be serializing to XML and sending over a socket using the PDA’s cellular modem. (If the person making the order had a PDA that did not have a cellular modem, the instance of FilmOrder could be serialized to a file.) The order could then be processed when the PDA was dropped into a docking cradle and synced. We are talking about data in a propriety form here, an instance of FilmOrder being converted into a generic form - XML - that can be universally understood.

The System.Xml.Serialization namespace contains classes and interfaces that support the serialization of objects to XML, and the deserialization of objects from XML. Objects are serialized to documents or streams using the XmlSerializer class. Let’s look at how you can use XmlSerializer. First, you need to define an object that implements a default constructor, such as FilmOrder:

  Public Class FilmOrder   ' These are Public because we have yet to implement   ' properties to provide program access.   Public name As String   Public filmId As Integer   Public quantity As Integer   Public Sub New()   End Sub   Public Sub New(ByVal name As String, _                  ByVal filmId As Integer, _                  ByVal quantity As Integer)     Me.name = name     Me.filmId = filmId     Me.quantity = quantity   End Sub End Class 

This class should be created in a console application. From there, we can move on to the module. Within the module’s Sub Main, create an instance of XmlSerializer, specifying the object to serialize and its type in the constructor (you need to make a reference to System.Xml.Serialization for this to work):

  Dim serialize As XmlSerializer = _   New XmlSerializer(GetType(FilmOrder)) 

Create an instance of the same type passed as a parameter to the constructor of XmlSerializer:

  Dim MyFilmOrder As FilmOrder = _   New FilmOrder("Grease", 101, 10) 

Call the Serialize() method of the XmlSerializer instance, and specify the stream to which the seri-alized object is written (parameter one, Console.Out) and the object to be serialized (parameter two, MyFilmOrder):

  serialize.Serialize(Console.Out, MyFilmOrder) Console.ReadLine() 

To make reference to the XmlSerializer object, you need to make reference to the System.Xml.Serialization namespace:

  Imports System.Xml Imports System.Xml.Serialization 

Running the module, the following output is generated by the preceding code:

 <?xml version="1.0" encoding="IBM437"?> <FilmOrder xmlns:xsd="http://www.w3.org/2001/XMLSchema"                        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">   <name>Grease</name>   <filmId>101</filmId>   <quantity>10</quantity> </FilmOrder>

This output demonstrates the default way in which the Serialize() method serializes an object:

  • Each object serialized is represented as an element with the same name as the class - in this case, FilmOrder.

  • The individual data members of the class serialized are contained in elements named for each data member - in this case, name, filmId, and quantity.

Also generated are the following:

  • The specific version of XML generated - in this case, 1.0

  • The encoding used - in this case, IBM437

  • The schemas used to describe the serialized object - in this case, www.w3.org/2001/XMLSchema-instance and www.w3.org/2001/XMLSchema

A schema can be associated with an XML document and describe the data it contains (name, type, scale, precision, length, and so on). Either the actual schema or a reference to where the schema resides can be contained in the XML document. In either case, an XML schema is a standard representation that can be used by all applications that consume XML. This means that applications can use the supplied schema to validate the contents of an XML document generated by the Serialize() method of the XmlSerializer object.

The code snippet that demonstrated the Serialize() method of XmlSerializer displayed the XML generated to Console.Out. Clearly, we do not expect an application to use Console.Out when it would like to access a FilmOrder object in XML form. The point was to show how serialization can be performed in just two lines of code (one call to a constructor and one call to method). The entire section of code responsible for serializing the instance of FilmOrder is presented here:

  Try     Dim serialize As XmlSerializer = _                 New XmlSerializer(GetType(FilmOrder))     Dim MyMovieOrder As FilmOrder = _             New FilmOrder("Grease", 101, 10)     serialize.Serialize(Console.Out, MyMovieOrder)     Console.Out.WriteLine()     Console.Readline() Catch ex As Exception     Console.Error.WriteLine(ex.ToString()) End Try 

The Serialize() method’s first parameter is overridden so that it can serialize XML to a file (the filename is given as type String), a Stream, a TextWriter, or an XmlWriter. When serializing to Stream, TextWriter, or XmlWriter, adding a third parameter to the Serialize() method is permissible. This third parameter is of type XmlSerializerNamespaces and is used to specify a list of namespaces that qualify the names in the XML-generated document. The permissible overrides of the Serialize() method are as follows:

 Public Sub Serialize(Stream, Object) Public Sub Serialize(TextWriter, Object) Public Sub Serialize(XmlWriter, Object) Public Sub Serialize(Stream, Object, XmlSerializerNamespaces) Public Sub Serialize(TextWriter, Object, XmlSerializerNamespaces) Public Sub Serialize(XmlWriter, Object, XmlSerializerNamespaces) Public Sub Serialize(XmlWriter, Object, XmlSerializerNamespaces, String) Public Sub Serialize(XmlWriter, Object, XmlSerializerNamespaces, String, String)

An object is reconstituted using the Deserialize() method of XmlSerializer. This method is overridden and can deserialize XML presented as a Stream, a TextReader, or an XmlReader. The overloads for Deserialize are as follows:

 Public Function Deserialize(Stream) As Object Public Function Deserialize(TextReader) As Object Public Function Deserialize(XmlReader) As Object Public Function Deserialize(XmlReader, XmlDeserializationEvents) As Object Public Function Deserialize(XmlReader, String) As Object Public Function Deserialize(XmlReader, String, XmlDeserializationEvents) As Object

Before demonstrating the Deserialize() method, we will introduce a new class, FilmOrder_Multiple. This class contains an array of film orders (actually an array of FilmOrder objects). FilmOrder_Multiple is defined as follows:

  Public Class FilmOrder_Multiple     Public multiFilmOrders() As FilmOrder     Public Sub New()     End Sub     Public Sub New(ByVal multiFilmOrders() As FilmOrder)         Me.multiFilmOrders = multiFilmOrders     End Sub End Class 

The FilmOrder_Multiple class contains a fairly complicated object, an array of FilmOrder objects. The underlying serialization and deserialization of this class is more complicated than that of a single instance of a class that contains several simple types, but the programming effort involved on your part is just as simple as before. This is one of the great ways in which the .NET Framework makes it easy for you to work with XML data, no matter how it is formed.

To work through an example of the deserialization process, first create a sample order stored as an XML file called Filmorama.xml:

  <?xml version="1.0" encoding="utf-8" ?> <FilmOrder_Multiple xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  xmlns:xsd="http://www.w3.org/2001/XMLSchema">    <multiFilmOrders>          <FilmOrder>             <name>Grease</name>             <filmId>101</filmId>             <quantity>10</quantity>          </FilmOrder>          <FilmOrder>             <name>Lawrence of Arabia</name>             <filmId>102</filmId>             <quantity>10</quantity>          </FilmOrder>          <FilmOrder>             <name>Star Wars</name>             <filmId>103</filmId>             <quantity>10</quantity>          </FilmOrder>    </multiFilmOrders> </FilmOrder_Multiple> 

Once the XML file is in place, the next step is to change your console application so it will take this XML file and deserialize its contents. Once you have the XML file in place, it is important to ensure that your console application has made the proper namespace references:

  Imports System.Xml Imports System.Xml.Serialization Imports System.IO 

Then, the following code demonstrates an object of type FilmOrder_Multiple being deserialized (or rehydrated) from a file, Filmorama.xml. This object is deserialized using this file in conjunction with the Deserialize() method of XmlSerializer:

  ' Open file, ..\Filmorama.xml Dim dehydrated As FileStream = _    New FileStream("Filmorama.xml", FileMode.Open) ' Create an XmlSerializer instance to handle deserializing, ' FilmOrder_Multiple Dim serialize As XmlSerializer = _    New XmlSerializer(GetType(FilmOrder_Multiple)) ' Create an object to contain the deserialized instance of the object. Dim myFilmOrder As FilmOrder_Multiple = _    New FilmOrder_Multiple ' Deserialize object myFilmOrder = serialize.Deserialize(dehydrated) 

Once deserialized, the array of film orders can be displayed:

  Dim SingleFilmOrder As FilmOrder For Each SingleFilmOrder In myFilmOrder.multiFilmOrders    Console.Out.WriteLine("{0}, {1}, {2}", _       SingleFilmOrder.name, _       SingleFilmOrder.filmId, _       SingleFilmOrder.quantity) Next Console.ReadLine() 

This example is just code that serializes an instance of type FilmOrder_Multiple. The output generated by displaying the deserialized object containing an array of film orders is as follows:

 Grease, 101, 10 Lawrence of Arabia, 102, 10 Star Wars, 103, 10

XmlSerializer also implements a CanDeserialize() method. The prototype for this method is as follows:

 Public Overridable Function CanDeserialize(ByVal xmlReader As XmlReader) _    As Boolean

If CanDeserialize() returns True, then the XML document specified by the xmlReader parameter can be deserialized. If the return value of this method is False, then the specified XML document cannot be deserialized.

The FromTypes()method of XmlSerializerfacilitates the creation of arrays that contain XmlSerializer objects. This array of XmlSerializerobjects can be used in turn to process arrays of the type to be serialized. The prototype for FromTypes()is shown here:

 Public Shared Function FromTypes(ByVal types() As Type) As XmlSerializer()

Before exploring the System.Xml.Serialization namespace, take a moment to consider the various uses of the term “attribute.”

Source Code Style Attributes

Thus far, you have seen attributes applied to a specific portion of an XML document. Visual Basic has its own flavor of attributes, as do C# and each of the other .NET languages. These attributes refer to annotations to the source code that specify information (or metadata) that can be used by other applications without the need for the original source code. We will call such attributes Source Code Style attributes.

In the context of the System.Xml.Serialization namespace, Source Code Style attributes can be used to change the names of the elements generated for the data members of a class or to generate XML attributes instead of XML elements for the data members of a class. To demonstrate this, we will use a class called ElokuvaTilaus, which contains data members named name, filmId, and quantity. It just so happens that the default XML generated when serializing this class is not in a form that can be readily consumed by an external application.

For example, assume that a Finnish development team has written this external application; hence, the XML element and attribute names are in Finnish (minus the umlauts), rather than English. To rename the XML generated for a data member, name, a Source Code Style attribute will be used. This Source Code Style attribute would specify that when ElokuvaTilaus is serialized, the name data member would be represented as an XML element, <Nimi>. The actual Source Code Style attribute that specifies this is as follows:

  <XmlElementAttribute("Nimi")> Public name As String 

ElokuvaTilaus, which means MovieOrder in Finnish, also contains other Source Code Style attributes:

  • <XmlAttributeAttribute(“ElokuvaId”)> specifies that filmId is to be serialized as an XML attribute named ElokuvaId.

  • <XmlAttributeAttribute(“Maara”)> specifies that quantity is to be serialized as an XML attribute named Maara.

ElokuvaTilaus is defined as follows:

  Imports System.Xml.Serialization Public Class ElokuvaTilaus   ' These are Public because we have yet to implement   ' properties to provide program access.   <XmlElementAttribute("Nimi")> Public name As String   <XmlAttributeAttribute("ElokuvaId")> Public filmId As Integer   <XmlAttributeAttribute("Maara")> Public quantity As Integer   Public Sub New()   End Sub   Public Sub New(ByVal name As String, _                  ByVal filmId As Integer, _                  ByVal quantity As Integer)       Me.name = name       Me.filmId = filmId       Me.quantity = quantity   End Sub End Class 

ElokuvaTilaus can be serialized as follows:

  Dim serialize As XmlSerializer = _     New XmlSerializer(GetType(ElokuvaTilaus)) Dim MyMovieOrder As ElokuvaTilaus = _     New ElokuvaTilaus("Grease", 101, 10) serialize.Serialize(Console.Out, MyMovieOrder) Console.Readline() 

The output generated by this code reflects the Source Code Style attributes associated with class ElokuvaTilaus:

 <?xml version="1.0" encoding="IBM437"?> <ElokuvaTilaus xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  xmlns:xsd="http://www.w3.org/2001/XMLSchema"  Elokuva Maara="10">     <Nimi>Grease</Nimi> </ElokuvaTilaus>

The value of filmId is contained in an XML attribute, ElokuvaId, and the value of quantity is contained in an XML attribute, Maara. The value of name is contained in an XML element, Nimi.

The example only demonstrates the Source Code Style attributes exposed by the XmlAttributeAttribute and XmlElementAttribute classes in the System.Xml.Serialization namespace. A variety of other Source Code Style attributes exist in this namespace that also control the form of XML generated by serialization. The classes associated with such Source Code Style attributes include XmlTypeAttribute, XmlTextAttribute, XmlRootAttribute, XmlIncludeAttribute, XmlIgnoreAttribute, and XmlEnumAttribute.




Professional VB 2005 with. NET 3. 0
Professional VB 2005 with .NET 3.0 (Programmer to Programmer)
ISBN: 0470124709
EAN: 2147483647
Year: 2004
Pages: 267

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net