AddThis Social Bookmark Button

Print

.NET Serialization, Part 2

by Wei-Meng Lee
11/03/2003

In my last article, I discussed how to serialize objects into a binary stream, as well as into a SOAP message. A third way to serialize an object is to serialize it into an XML document. There are many advantages to XML serialization -- XML documents are platform-agnostic, since they is in plain text format and that makes cross platform communications very easy. XML documents are also easy to read and modify, which makes XML a very flexible format for data representation.

In this article, I will illustrate XML serialization with an example and show you some of its uses.

Defining Our Sample Class

Let's define a class so that we can see how XML serialization works. For this example, I have defined a Member class that allows you to store information about a person, such as name, addresses, and date of birth. Here is the class definition:

Public Class Member
  Private age As Integer
  Public Name As CName
  Public Addresses() As CAddress
  Public DOB As Date
  ReadOnly Property currentAge()
    Get
      age = DateDiff(DateInterval.Year, DOB, Now)
      Return age
    End Get
  End Property
End Class

Public Class CName
  Private pFirstName, pLastName As String
  Property FirstName()
    Get
      Return pFirstName
    End Get
    Set(ByVal Value)
      pFirstName = Value
    End Set
  End Property
  Property LastName()
    Get
      Return pLastName
    End Get
    Set(ByVal Value)
      pLastName = Value
    End Set
  End Property
End Class

Public Class CAddress
  Public Line1 As String
  Public Line2 As String
  Public City As String
  Public Country As String
  Public Postal As String
End Class

I have deliberately designed my class so that I can illustrate the various aspects of XML serialization. Here are the specifics:

  • The Member class contains both private and public variables. It also contains a READONLY property.
  • The Member class contains a public array containing the addresses of a Member.
  • The Member class contains a variable of Date data type.
  • The CName class contains two private variables and two properties.
  • The CAddress contains only public variables.
.NET & XML

Related Reading

.NET & XML
By Niel Bornstein

To serialize a Member object into a XML document, I used the XMLSerializer class from the System.Xml.Serialization namespace:

Imports System.Xml.Serialization

'========XML Serialization=========
Sub XMLSerialize(ByVal mem As Member)
  Dim wri As New StreamWriter("c:\Members.xml")
  Try
    Dim ser As New XmlSerializer(GetType(Member))
    ser.Serialize(wri, mem)
  Catch ex As Exception
    MsgBox(ex.ToString)
  Finally
    wri.Close()
  End Try
End Sub

Assuming I have the following object declaration:

Dim mem As New Member
Dim memName As New CName
memName.FirstName = "Wei-Meng"
memName.LastName = "Lee"
mem.Name = memName
mem.DOB = "5/1/1972"

Dim address As New CAddress
address.Line1 = "One Way Street"
address.Line2 = "Infinite Loop"
address.Country = "SINGAPORE"
address.Postal = "456123"

Dim addresses(1) As CAddress
addresses(0) = address
addresses(1) = address
mem.Addresses = addresses

To serialize the Member object, invoke the XMLSerialize() method, as shown earlier:

XMLSerialize(mem)

The XML document generated looks like this:

<?xml version="1.0" encoding="utf-8"?>
<Member xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <Name>
    <FirstName xsi:type="xsd:string">Wei-Meng</FirstName>
    <LastName xsi:type="xsd:string">Lee</LastName>
  </Name>
  <Addresses>
    <CAddress>
      <Line1>One Way Street</Line1>
      <Line2>Infinite Loop</Line2>
      <Country>SINGAPORE</Country>
      <Postal>456123</Postal>
    </CAddress>
    <CAddress>
      <Line1>One Way Street</Line1>
      <Line2>Infinite Loop</Line2>
      <Country>SINGAPORE</Country>
      <Postal>456123</Postal>
    </CAddress>
  </Addresses>
  <DOB>1972-05-01T00:00:00.0000000-07:00</DOB>
</Member>

As you can see, the object is serialized into an XML document with a format corresponding to the structure of the object. (To de-serialize the XML document, simply use the Deserialize() method from the XMLSerializer class.)

Here are some important points to note:

  • The City information is not persisted in the XML document, as it is not assigned in the object. I will show you later how to ensure that an empty element is inserted, even though a value is not assigned.
  • All READ/WRITE properties in the object are persisted in the XML document, except the READONLY currentAge property in the Member class.
  • Only public variables are persisted; private variables are not persisted in XML serialization.
  • The default name for each element in the XML document takes after the variable (or class) name. In most cases this is desirable, except in the case where the individual address is represented by the <caddress> element (which may not be too obvious to the person reading the XML document).

Despite the fairly automated task performed by the XMLSerializer object, you can customize the way the XML document is generated. Let's modify our classes with a few attributes. Here is the modified class:

<XmlRoot("MemberInformation", _
          Namespace:="http://www.mycompany.com", _
          IsNullable:=True)> _
Public Class Member
  Private age As Integer
  ' specify the element name to be MemberName
  <XmlElement("MemberName")> _
  Public Name As CName
  ' specify the sub-element(s) of Addresses to be Address
  <XmlArrayItem("Address")> _
  Public Addresses() As CAddress
  Public DOB As Date

  ReadOnly Property currentAge()
    Get
      age = DateDiff(DateInterval.Year, DOB, Now)
      Return age
    End Get
  End Property
End Class

Public Class CName
  Private pFirstName, pLastName As String
  Property FirstName()
    Get
      Return pFirstName
    End Get
    Set(ByVal Value)
      pFirstName = Value
    End Set
  End Property
  Property LastName()
    Get
      Return pLastName
    End Get
    Set(ByVal Value)
      pLastName = Value
    End Set
  End Property
End Class

Public Class CAddress
  Public Line1 As String
  Public Line2 As String
  ' empty element if city is not specified
  <XmlElement(isnullable:=True)> _
    Public City As String
  ' specify country and postal as attribute
  <XmlAttributeAttribute()> _
    Public Country As String
  <XmlAttributeAttribute()> _
    Public Postal As String
End Class

When the class is serialized, the XML document looks like this:

<?xml version="1.0" encoding="utf-8"?>
<MemberInformation xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
		xmlns="http://www.mycompany.com">
  <MemberName>
    <FirstName xsi:type="xsd:string">Wei-Meng</FirstName>
    <LastName xsi:type="xsd:string">Lee</LastName>
  </MemberName>
  <Addresses>
    <Address Country="SINGAPORE" Postal="456123">
      <Line1>One Way Street</Line1>
      <Line2>Infinite Loop</Line2>
      <City xsi:nil="true" />
    </Address>
    <Address Country="SINGAPORE" Postal="456123">
      <Line1>One Way Street</Line1>
      <Line2>Infinite Loop</Line2>
      <City xsi:nil="true" />
    </Address>
  </Addresses>
  <DOB>1972-05-01T00:00:00.0000000-07:00</DOB>
</MemberInformation>

Here are the uses of each attribute:

<XmlRoot("MemberInformation", _
          Namespace:="http://www.mycompany.com", _
          IsNullable:=True)> _
Public Class Member
...

Sets the root element name of the XML document to be MemberInformation (default element name is Member, which follows the class name), with a specific namespace. The IsNullable attribute indicates if empty elements must be displayed.

<XmlElement("MemberName")> _
     Public Name As CName
...

Specifies that the element name MemberName be used in place of the current variable name (as defined in the class as CName).

<XmlArrayItem("Address")> _
  Public Addresses() As CAddress
...

Specifies that the following variable is repeating (an array) and that each repeating element be named as Address.

<XmlElement(isnullable:=True)> _
  Public City As String
...

Indicates that the document must include the City element even if it is empty.

<XmlAttributeAttribute()> _
  Public Country As String

Indicates that the Country information be represented as an attribute.

XML Serialization Needs a Default Constructor

There is one more thing that you need to take note of when doing XML serialization. If your class has a constructor (as the following example shows), then you would also need a default constructor:

Public Class Points
  Sub New(ByVal x As Single, ByVal y As Single)
  End Sub

  Property x()
    Get
    End Get
    Set(ByVal Value)
    End Set
  End Property

  Property y()
    Get
    End Get
    Set(ByVal Value)
    End Set
  End Property
End Class

The above example will result in an error when you try to perform XML serialization on it. To solve the problem, simply add a default constructor to your class definition:

Public Class Points
  Sub New()
  End Sub

  Sub New(ByVal x As Single, ByVal y As Single)
  End Sub

  Property x()
    Get
    End Get
    Set(ByVal Value)
    End Set
  End Property

  Property y()
    Get
    End Get
    Set(ByVal Value)
    End Set
  End Property
End Class

Uses of XML Serialization

Now that we have seen how XML serialization works, what are its uses? For one, it can help you to preserve the state of your object (just like the binary and SOAP serialization that you saw in my last article) and makes transportation easy. More significantly, I often use XML serialization to manage configuration files. I can define a class to store configuration information and use XML serialization to persist it on file. By doing so, I have the flexibility to modify the configuration information easily, since the information is now represented in XML; at the same time, I can programmatically manipulate the configuration information by accessing the object's properties and methods.

Wei-Meng Lee (Microsoft MVP) http://weimenglee.blogspot.com is a technologist and founder of Developer Learning Solutions http://www.developerlearningsolutions.com, a technology company specializing in hands-on training on the latest Microsoft technologies.


Return to ONDotnet.com