Writing XML with XMLSerializer.

The XMLSerializer:

Recently a friend of mine and I were discussing the best way to serialize a Dataset to XML while being able to control the structure of the XML.  With a dataset we could easily use the dataset.WriteToXml method to write the dataset to XML.  However the only control we have in the structure of the XML with this method is through our dataset and how we load it.  Another option is to Loop through our Dataset and write it out to XML utilizing the XMLWriter giving us full control over the structure of the XML; however. Depending upon the size of our Dataset and intended XML this can end up being quite cumbersome.  We could load the Dataset directly into the XMLSerializer to write out our XML, but once again the only control we have with the schema of our XML will be in how we built our table.  Thus we are left with our topic for this entry.  How do we serialize XML from a dataset with custom attributes using the XMLSerializer? 

For the purpose of this project we are going to do this in a single web page.  Inside our web page we are going to create 2 classes and a method to do the actual serialization.  Our environment is Visual Studio 2005 and VB.Net.

Now let’s go ahead and open up VS2005 and create a new web application/project and name it XMLWrite.  Once we have our project open we can delete the default page, and add a new one named xmlserialize.aspx.  Go ahead and save this project as we will be revisiting the project in the other 2 parts to this series at a later date. 

Now let’s go ahead and get to some coding.  Start off by going to the code view of your page.  What we need to start off with is our import statements. 

Imports System
Imports System.Data
Imports System.Data.Sql
Imports System.Data.SqlClient
Imports System.Xml
Imports System.Xml.Serialization
Imports System.IO
Imports System.Collections.Generic    

I’ve included in this project an Address Book database with 2 tables (Person and Address) to use for our example.  Start off with making 3 Classes in your project. 

Public Class AddressBook
    <XmlElement("Entry")> _
    Public Person As New List(Of Person)
End Class 

Public Class Person
    Public FullName As String
    <XmlElement(""Address"")> _
    Public Address As New List(Of Address)
End Class 

Public Class Address
    <XmlAttribute("Type")> _
    Public AddressType As String
    Public AddressLine1 As String
    Public AddressLine2 As String
    Public City As String
    Public State As String
    Public Postal As Integer

End Class 

There are 2 areas’ I want to point out in our class’s here.  The first is that we have used generics to instantiate Person in our Class AddressBook and Address in our Class Person to take advantage of their built in “Add” method.  The 2nd area is the decoration in our Address Class.  <XmlAttribute(“Type”)> tells the XMLSerializer to set AddressType as an attribute of the node Address.  The XMLSerializer will set the name of the element, root, and attributes to the name of the object unless we specify it specifically as we did in the Attribute decoration. 

Private Sub SerializeXML()
        Dim sqlCon As New SqlConnection(ConfigurationManager.ConnectionStrings("addressbook").ConnectionString)
        Dim CmdTxt As String = "spi_GetAddress"
        Dim SqlCmd As New SqlCommand(CmdTxt, sqlCon)
        SqlCmd.CommandType = CommandType.StoredProcedure
        Dim sqlDS As New DataSet
        Dim sqlDA As New SqlDataAdapter(SqlCmd)
        Dim xns As XmlSerializerNamespaces = New XmlSerializerNamespaces
        Dim mySerializer As New XmlSerializer(GetType(AddressBook))
        Dim sWriter As New StreamWriter(Server.MapPath("address.xml"))
        Dim oBook As New AddressBook

        xns.Add(String.Empty, String.Empty)
        sqlDA.Fill(sqlDS)
        
       
For Each Row As DataRow In sqlDS.Tables(0).Rows
            Dim oPerson As New Person
            Dim oAddress As New Address

            oAddress.AddressLine1 = Row("AddressLine1").ToString
            oAddress.AddressLine2 = Row("AddressLine2").ToString
            oAddress.City = Row("city").ToString
            oAddress.State = Row("state").ToString
            oAddress.Postal = Row("postal").ToString
            oAddress.AddressType = Row("AddressType").ToString
            oPerson.FullName = Row("FullName").ToString
            oPerson.Address.Add(oAddress)
            oBook.Person.Add(oPerson)
        Next
        mySerializer.Serialize(sWriter, oBook, xns)

        SqlCmd.Connection.Close()
        SqlCmd.Dispose()
End Sub

Pay close attention to the line:

Dim xns As XmlSerializerNamespaces = New XmlSerializerNamespaces

xns.Add(
String.Empty, String.Empty)
 

Here we are resetting the name space that The XMLSerializer adds to the root by default and adding an empty string so that we have a root element of our xml with no namespaces.   The Final step to this look at customizing our XML from a XMLSerializer is to call our Method from the page load and execute it giving us a final XML. 

<?xml version="1.0" encoding="utf-8"?>
<AddressBook>
  <Entry>
    <FullName>John Doe</FullName>
      <Address Type="Home">
        <AddressLine1>100 One Street</AddressLine1>
        <AddressLine2 />
        <City>Dallas</City>
        <State>Tx</State>
        <Postal>75240</Postal>
      </Address>
  </Entry>
  <Entry>
    <FullName>Jane Doe</FullName>
      <Address Type="Business">
        <AddressLine1>1532 LBJ Freeway</AddressLine1>
        <AddressLine2>Suite 300</AddressLine2>
        <City> Dallas</City>
        <State>Tx</State>
        <Postal>75248</Postal>
      </Address>
  </Entry>
</AddressBook>  

Enjoy

 Dave Yancey

XMLWrite.zip (615.03 kb)

 

11 Comments

  • You could have stayed with the .WriteToXml method and then done a XSL Transformation on the resulting XML to get the format you want. While your object serialization works just as well, I have a feeling the XSL Transformation might be a bit more lightweight. It seems a lot of people have missed the magic of XSLT, but it is another language in itself so I can understand the hesitance.

  • Thank you for your comment.

    You're right there are many different ways of achieving the same results. There are advantages / disadvantages to each solution, the purpose of this one is to show how to build the XML using the XMLSerializer.

    Which method you choose really depends upon the business needs of your application.

  • Can you make a C# version please?

  • You bet, give me a day or two and I'll post a C# version.

  • Great explanations - really helped me get the concepts and was able to easily adapt to my code - THANKS

    Have you done anything with deserialization, yet?

  • When I first wrote the app to use for this entry I deserialized the xml back into the object just to ensure that the app / design was working the way I wanted it to. At this time I dont have any other examples on deserialization.

  • Would you mind sharing what you used for the deserialization?

  • Would be very very helpful having a C# version...could u please post it?

  • Here's where I posted my C# version.

    http://weblogs.asp.net/davidyancey/archive/2008/02/08/xmlserializer-in-c.aspx

    @WendyC

    I'll be writing up a detailed post on deserialization in the next few days.

  • I want to serialize a dataset object, but not into a file.
    I want to go straight into an SQL (xml data type) field.

    Can you show me how to do that?

    Code I have below doesn't work.

    myDS = DataSet object (already constructed and filled)

    Dim myStream as System.IO.Stream

    mySerializer = XmlSerializer = New XmlSerializer(GetType(DataSet))

    mySerializer.Serialize(myStream,myDS)???

  • Hmm that was weird, my comment got eaten. Anyway I wished to say that it is really nice to recognize that another individual else also described this as I had problems acquiring the similar data elsewhere.

    This was the first location that advised me
    that the remedy. Quite a ton of thanks.

Comments have been disabled for this content.