Improve Your Technology

Just another blog for techology

XML Serialization in the .NET Framework

XML Serialization in the .NET Framework 

Dare Obasanjo
Microsoft Corporation

January 23, 2003

Overview of XML Serialization in the .NET Framework

The primary purpose of XML serialization in the .NET Framework is to enable the conversion of XML documents and streams to common language runtime objects and vice versa. Serialization of XML to common language runtime objects enables one to convert XML documents into a form where they are easier to process using conventional programming languages. On the other hand, serialization of objects to XML facilitates persisting or transporting the state of such objects in an open, standards compliant and platform agnostic manner.

XML serialization in the .NET Framework supports serializing objects as either XML that conforms to a specified W3C XML Schema Definition (XSD) schema or that is conformant to the serialization format defined in section five of the SOAP specification. During XML serialization, only the public properties and fields of an object are serialized. Also, type fidelity is not always preserved during XML serialization. This means that if, for instance, you have a Book object that exists in the Library namespace, there is no guarantee that it will be deserialized into an object of the same type. However, this means that objects serialized using the XML serialization in the .NET Framework can be shipped from one machine to the other without requiring that the original type be present on the target machine or that the XML is even processed using the .NET Framework. XML serialization of objects is a useful mechanism for those who want to provide or consume data using platform agnostic technologies such as XML and SOAP.

XML documents converted to objects by the XML serialization process are strongly typed. Data type information is associated with the elements and attributes in an XML document through a schema written in the W3C XML Schema Definition (XSD) Language. The data type information in the schema allows the XmlSerializer to convert XML documents to strongly typed classes.

For more information about XML serialization in the .NET Framework, read the SDK documentation topic entitled XML and SOAP Serialization.

The Book Inventory Application

In my previous articles, I created an XML document that listed all my books and described their availability in my personal library. Upon reflection, I decided that I’d prefer a GUI interface for viewing and manipulating the document instead of editing the raw XML file in a text editor. The first step I took in creating this application was to look at the classes in the System.Windows.Forms namespace to see if any could satisfy my needs out of the box. The DataGrid class looked promising.

The description of potential data sources for the DataGrid class included single dimensional arrays, which struck a chord because I imagined that a sequential listing of books is something that could be mapped to an array by XML serialization. I decided to give this a try by converting the schema shown below to a C# class.

<?xml version="1.0" encoding="UTF-8" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
targetNamespace="urn:xmlns:25hoursaday-com:my-bookshelf" 
xmlns:bk="urn:xmlns:25hoursaday-com:my-bookshelf" 
elementFormDefault="qualified">
   <xs:element name="books">
      <xs:complexType>
         <xs:sequence>
            <xs:element name="book" type="bk:bookType" 
maxOccurs="unbounded" />
         </xs:sequence>
      </xs:complexType>
   </xs:element>
   <xs:complexType name="bookType">
      <xs:sequence>
         <xs:element name="title" type="xs:string" />
         <xs:element name="author" type="xs:string" />
         <xs:element name="publication-date" type="xs:date" />
      </xs:sequence>
      <xs:attribute name="publisher" type="xs:string" />
      <xs:attribute name="on-loan" type="xs:string" />
   </xs:complexType>

</xs:schema>

The .NET Framework SDK provides the XML Schema Definition Tool xsd.exe that can be used to convert XSD schemas to C# classes. I converted my schema file to C# source file issuing the following commands on the command line:

                xsd.exe  /c books.xsd

The generated C# class is decorated with attributes that provide information on how the XmlSerializer converts the class to XML. The XmlRootAttribute, XmlElementAttribute, and XmlAttributeAttribute attributes are used to specify which classes, fields, or properties become the root, element, and attribute nodes in the generated XML. The class generated from the schema is shown below.

using System.Xml.Serialization;
 /// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(Namespace=
"urn:xmlns:25hoursaday-com:my-bookshelf")]
[System.Xml.Serialization.XmlRootAttribute("books", 
Namespace="urn:xmlns:25hoursaday-com:my-bookshelf", IsNullable=false)]
public class books {
      /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute("book")]
    public bookType[] book;
}
 /// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(Namespace=
"urn:xmlns:25hoursaday-com:my-bookshelf")]
public class bookType {
     /// <remarks/>
    public string title;
      /// <remarks/>
    public string author;
     /// <remarks/>
   [System.Xml.Serialization.XmlElementAttribute("publication-date", 
DataType="date")]      
    public System.DateTime publicationdate;
     /// <remarks/>
    [System.Xml.Serialization.XmlAttributeAttribute()]
    public string publisher;
      /// <remarks/>
    [System.Xml.Serialization.XmlAttributeAttribute("on-loan")]
    public string onloan;

}

Note   The attribute that annotates the publicationdate field has a DataType property. There is no type in the .NET Framework that matches the type xs:date completely. The closest match is System.DateTime, which stores date and time data. Specifying the DataType property as a “date” ensures that the XmlSerializer will only serialize the date part of the DateTime object.

The XmlSerializer mapped the multiple book elements of type bookType in my schema to an array of bookType objects named book. I thought I was ready to bind my classes to the DataGrid until I noticed a section of the documentation on Data Sources for the DataGrid Control which pointed out that the objects in an array must have public properties if they are to be bound to a DataGrid. Since the XSD tool created public fields, I had to fix my classes by making the fields private and exposing them through properties instead. Then, I also had to move the XML serialization specific attributes from the fields to the properties because the XmlSerializer only checks for attributes on public fields and properties. Below is the altered bookType class.

/// <remarks/>
   [System.Xml.Serialization.XmlTypeAttribute(Namespace=
"urn:xmlns:25hoursaday-com:my-bookshelf")]
   public class bookType 
   {
      /// <remarks/>
      private string _title;
      public string title{
         get{ return _title; }
         set { _title = value; }
      }
         /// <remarks/>
      private string _author;
      public string author
      {
         get{ return _author; }
         set { _author = value; }
      }
     /// <remarks/>
      private  System.DateTime _publicationdate;
      [System.Xml.Serialization.XmlElementAttribute("publication-date",
 DataType="date")]      
      public System.DateTime publicationdate
      {
         get{ return _publicationdate; }
         set { _publicationdate = value; }
      }
     private string _publisher;
      /// <remarks/>
      [System.Xml.Serialization.XmlAttributeAttribute()]
      public string publisher
      {
        get{ return _publisher; }
         set { _publisher = value; }
      }
       private  string _onloan;
      [System.Xml.Serialization.XmlAttributeAttribute("on-loan")]      
      public string onloan
      {
         get{ return _onloan; }
         set { _onloan = value; }
      }

   }

With the aforementioned changes, it is now possible to bind my list of books as XML to a DataGrid. Firing up the Visual Studio® .NET forms designer, I quickly dragged and dropped a DataGrid onto a form, along with a couple of buttons for navigation purposes. The final step was to add some code to ensure that the DataGrid was bound to my XML once the form was loaded. The Form_Load method in my class is shown below.

private void Form1_Load(object sender, System.EventArgs e)
     {
       try{
         TextReader reader = new StreamReader("books.xml");
         XmlSerializer serializer = new XmlSerializer(typeof(books));
         myBooks = (books)serializer.Deserialize(reader);
         reader.Close();
          //currency manager used for cursoring through book array in UI
         currencyManager = 
(CurrencyManager)dataGrid1.BindingContext[myBooks.book];
          dataGrid1.DataSource= myBooks.book;
        }catch(XmlException xe){
         MessageBox.Show (xe.Message, "XML Parse Error", 
                MessageBoxButtons.OK, MessageBoxIcon.Error);
        }catch(InvalidOperationException ioe){
         MessageBox.Show (ioe.InnerException.Message, "XML 
Serialization Error", 
                MessageBoxButtons.OK, MessageBoxIcon.Error);
  }

}

And that’s all it takes. Shown below is the XML document I plan to edit with my application.

<books xmlns="urn:xmlns:25hoursaday-com:my-bookshelf" >
  <book publisher="QUE">
    <title>XML By Example</title>
    <author>Benoit Marchal</author>
    <publication-date>1999-12-31</publication-date>
  </book>
  <book publisher="Addison Wesley" on-loan="Dmitri">
    <title>Essential C++</title>
    <author>Stanley Lippman</author>
    <publication-date>2000-10-31</publication-date>
  </book>
  <book publisher="WROX">
    <title>XSLT Programmer's Reference</title>
    <author>Michael Kay</author>
    <publication-date>2001-04-30</publication-date>
  </book>
  <book publisher="Addison Wesley" on-loan="Sanjay">
    <title>Mythical Man Month</title>
    <author>Frederick Brooks</author>
    <publication-date>1995-06-30</publication-date>
  </book>
  <book publisher="Apress">
    <title>Programmer's Introduction to C#</title>
    <author>Eric Gunnerson</author>
    <publication-date>2001-06-30</publication-date>
  </book>

</books>

Figure 1 below shows a DataGrid bound to the above XML document in my Book Inventory application .

 

Figure 1. The Book Inventory application

It should be noted that although my application allows me to edit the contents of my XML document bound to the DataGrid, I cannot add or delete new books to my inventory file. The inability to add modify the number of books through the DataGrid is a limitation imposed on it when bound to arrays. This issue does not exist when bound to other data sources.

For the purpose of completeness, I should highlight an alternative approach to solving my data binding problem. I could have loaded the XML document and schema into a DataSet using the ReadXml() and ReadXmlSchema() methods respectively, then bound that to the DataGrid. Descriptions of how to use this alternate approach are available in the .NET SDK documentation in the section entitled Generating DataSet Relational Structure from XML Schema (XSD). A code example using the DataSet class instead of XML serialization is also included in the download file for the article.

SOAP Serialization

Besides binary serialization, you can also serialize objects into a platform-agnostic format: you can serialize it into a SOAP message.

The SOAPSerialize() subroutine serializes a BookMark object into an XML document (when building this code, you need a reference to the System.Runtime.Serialization.Formatters.Soap.dll assembly):

Imports System.Runtime.Serialization.Formatters.Soap

 

‘========SOAP Serialization=========

Sub SOAPSerialize(ByVal BkMk As BookMark)

  Dim fs As New FileStream(“c:\BookMarks.xml”, _

                FileMode.Create, FileAccess.Write)

  Dim formatter As New SoapFormatter

  formatter.Serialize(fs, BkMk) ‘ serialize to file stream

  fs.Close()

End Sub

So, instead of using the BinaryFormatter class, I have replaced it with the SoapFormatter class.

The SOAPDeserialize() function reads the XML document (containing the SOAP message), de-serializes it, and returns a BookMark object:

Function SOAPDeserialize(ByVal filename As String) As BookMark

  Dim fs As New FileStream(filename, FileMode.Open, _

                FileAccess.Read)

  Dim formatter As New SoapFormatter

  Return formatter.Deserialize(fs) ‘ serialize to file stream

End Function

Here is how you can call the previous two methods:

‘========SOAP Serialization=========

SOAPSerialize(BM1)

newBM = SOAPDeserialize(“c:\ BookMarks.xml”)

‘—printing the object graph

Print(newBM)

And the SOAP message generated would look something like this:

<SOAP-ENV:Envelope

 xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance&#8221;

 xmlns:xsd=”http://www.w3.org/2001/XMLSchema&#8221;

 xmlns:SOAP-ENC=”http://schemas.xmlsoap.org/soap/encoding/&#8221;

 xmlns:SOAP-ENV=”http://schemas.xmlsoap.org/soap/envelope/&#8221;

 xmlns:clr=”http://schemas.microsoft.com/soap/encoding/clr/1.0&#8243;

SOAP-ENV:encodingStyle=”http://schemas.xmlsoap.org/soap/encoding/”&gt;

 

<SOAP-ENV:Body>

   <a1:BookMark id=”ref-1″

   xmlns:a1=”http://schemas.microsoft.com/clr/nsassem/WindowsApplication1

/WindowsApplication1%2C%20Version%3D1.0.1125.1874%2C%20Culture%3Dneutral

%2C%20PublicKeyToken%3Dnull”>

      <pURL id=”ref-3″>http://www.amazon.com</pURL&gt;

      <pDescription id=”ref-4″>Amazon.com Web site</pDescription>

      <pNextURL href=”#ref-5″/>

   </a1:BookMark>

   <a1:BookMark id=”ref-5″

   xmlns:a1=”http://schemas.microsoft.com/clr/nsassem/WindowsApplication1

   /WindowsApplication1%2C%20Version%3D1.0.1125.1874%2C%20Culture%3Dneutral%2C

   %20PublicKeyToken%3Dnull”>

      <pURL id=”ref-6″>http://www.oreilly.com</pURL&gt;

      <pDescription id=”ref-7″>O’Reilly Web Site</pDescription>

      <pNextURL xsi:null=”1″/>

   </a1:BookMark>

</SOAP-ENV:Body>

 

</SOAP-ENV:Envelope>

Uses of Serialization

Serialization is one good way to preserve the state of an object. It is commonly used for network communications, where you need to pass an object from one machine to another. Another good use of serialization is to use it to clone an object — serialize an object, de-serialize it, and assign to another object. Voilà! You have an identical copy of the object.

Advertisements

September 16, 2008 - Posted by | Serialization, Technology, XML Serialization | , ,

1 Comment »

  1. These are actually wonderful ideas in regarding blogging.
    You have touched some pleasant points here. Any
    way keep up wrinting.

    Comment by Removal Of Bee Hives Randpark Ridge | May 1, 2014 | Reply


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: