Listing 1 Definition of a "Book" class for both formats

Book definition for Xml-Elements model	Book definition for XmlAttributes model
Notice how each property in the class is decorated with XmlAttribute.
public class Book
{
    /// <summary>
    /// title of the book
    /// </summary>
    private string _title;
    public string Title
    {  get { return _title; }
       set { _title = value; } }

    /// <summary>
    /// ISBN of the book
    /// </summary>
    private string _isbn;
    public string ISBN
    {   get { return _isbn; }
        set { _isbn = value; } }

    /// <summary>
    /// Author of the Book
    /// </summary>
    private string _author;
    public string Author
    {   get { return _author; }
        set { _author = value; } }

    /// <summary>
    /// Default constructor: Needed for Xml serialization
    /// </summary>
    public Book() {    }

    
    /// constructor
    public Book(string title, string isbn,      string author)
    {
        Title = title;
        ISBN = isbn;
        Author = author;
    }
 }
	public class Book
{
    /// <summary>
    /// title of the book
    /// </summary>
    private string _title;
    [XmlAttribute("Title")]
    public string Title
    {   get { return _title; }
        set { _title = value; } }

    /// <summary>
    /// ISBN of the book
    /// </summary>
    private string _isbn;
    [XmlAttribute("ISBN")]
    public string ISBN
    {   get { return _isbn; }
        set { _isbn = value; }  }
    /// <summary>
    /// Author of the Book
    /// </summary>
    private string _author;
    [XmlAttribute("Author")]
    public string Author
    {   get { return _author; }
        set { _author = value; } }

    /// <summary>
    /// Default constructor: Needed for Xml serialization
    /// </summary>
    public Book()
    {
    }

    /// constructor
    public Book(string title, string isbn, string author)
    {
        Title = title;
        ISBN = isbn;
        Author = author;
    }
    
}


Listing 2 Code to serialize and deserialize

Book book = new Book("Visual C# 2005 A Developer's Notebook",
"0-596-00799-X", "Jess Liberty");
XmlSerializer serializer = new XmlSerializer(book.GetType());

MemoryStream memoryStream = new MemoryStream();
XmlTextWriter writer = new XmlTextWriter(memoryStream, Encoding.UTF8);
serializer.Serialize(writer, book);

// get the stream from the writer
memoryStream = writer.BaseStream as MemoryStream;

// apply encoding to the stream 
UTF8Encoding encoding = new UTF8Encoding();
string xml = encoding.GetString(memoryStream.ToArray()).Trim();

// Following code would deserialize xml into Book object
// get the byte stream from the string in utf-8 encoding
Byte[] bytes = encoding.GetBytes(xml);

// create a stream from the bytes
memoryStream = new MemoryStream(bytes);

Book deserializedBook = serializer.Deserialize(memoryStream) as Book; //Deserialization

Listing 3 Serialized XML for an instance of a "Book" class

XML-Element format	XML-Attribute format
<?xml version="1.0" encoding="utf-8" ?>
   <Book xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
     <Title>Visual C# 2005 A Developer's Notebook</Title> 
     <ISBN>0-596-00799-X</ISBN> 
     <Author>Jesse Liberty</Author> 
    </Book>	<?xml version="1.0" encoding="utf-8" ?> 
<Book xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" Title="Visual C# 2005 A Developer's
Notebook" ISBN="0-596-00799-X" Author="Jesse Liberty" />

Listing 4 Definition of a "Doctor" class and a "Patient" class

Class definition for Doctor	Class definition for Patient
[XmlRoot("Physician")]
public class Doctor : Person
{
    private string _specialization;
    [XmlAttribute("Specialization")]
    public string Specialization
    {   get { return _specialization; }
        set { _specialization = value;}}

    private List<Patient> _patients = 
                    new List<Patient>();
    [XmlArrayItem(typeof(Patient))]
    public List<Patient> Patients
    {   get { return _patients; }
        set { _patients = value;}}
    
    /// <summary>
    /// default constrcutor
    /// </summary>
    public Doctor(){}
    
    // constructor
    public Doctor
    (   string fName, 
        string lName, 
        string specialization
    ) : base(fName, lName)
    {
        Specialization = specialization;
    }
    
    // function to add a patient
    public void AddPatient(Patient patient)
    {
        Patients.Add(patient);
    }
    
    //function to remove a patient
    public void RemovePatient(Patient pat)
    {
        Patients.Remove(pat);
    }
}
	public class Patient : Person
{
    private string _mrn;
         [XmlAttribute("Medical_Record_Number")]
    public string MRN
    {
        get { return _mrn; }
        set { _mrn = value; }
    }

    private string _diagnosis;
    [XmlAttribute("Diagnosis")]
    public string Diagnosis
    {
        get { return _diagnosis; }
        set { _diagnosis = value; }
    }
    
    /// <summary>
    /// default constructor
    /// </summary>
    public Patient(){}
    
    //constructor
    public Patient
    (   string fName, 
        string lName 
    ) : base(fName, lName)
    {
    }
   
}

Listing 5 Serialized XML for an instance of a "Doctor" class

<?xml version="1.0" encoding="utf-8" ?>
 	<Physician
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
		 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
		 FirstName="Austin" LastName="Szubryt" Specialization="Paediatrics">
 	<Patients>
<Patient FirstName="Malcom" LastName="Speed" Medical_Record_Number="M555678999" Diagnosis="Burns" />
<Patient FirstName="Amit" LastName="Jain" Medical_Record_Number="M333875452" Diagnosis="Shortness of breath" />
   </Patients>
   </Physician>

Listing 6 BusinessBase class definition

using System;
using System.IO;
using System.Reflection;
using System.Text;
using System.Xml;
using System.Xml.Serialization;

namespace DNDJ_XmlSerialization
{
public class BusinessBase
{
/// <summary>
/// function to copy all properties from bBaseToCopy into 'this'(Copy Constructor)
/// </summary>
/// <param name="bBaseToCopy"></param>
public virtual void Copy(BusinessBase bBaseToCopy)
{
    // get all the properties from 'this'
    PropertyInfo[] properties = this.GetType().GetProperties();

    // loop through the properties
    foreach (PropertyInfo property in properties)
    {
        if (property.CanWrite && property.CanRead) // if there is a Set & Get Method
        {
            //Invoke the "set" on 'this' and "get" on 'bBaseToCopy'
            property.GetSetMethod().Invoke(this, 
                new object[] { property.GetGetMethod().Invoke(bBaseToCopy, null) });
        }
    }
}

/// <summary>
/// Function to convert 'this' into XML string.  Could be overridden in derived class
/// if desired.  we use UTF-8 encoding since SqlServer would understand only UTF-8
/// </summary>
/// <returns></returns>
public virtual string ToXML()
{
    // create a memory stream/text writer for UTF-8 encoding (1-char 1-byte)
    MemoryStream memoryStream = new MemoryStream();
    XmlTextWriter writer = new XmlTextWriter(memoryStream, Encoding.UTF8);

    // create the serializer and serialize 'this'
    XmlSerializer serializer = new XmlSerializer(this.GetType());
    serializer.Serialize(writer, this);

    // get the stream from the writer
    memoryStream = writer.BaseStream as MemoryStream;

    // apply encoding to the stream and return the string
    UTF8Encoding encoding = new UTF8Encoding();
    string xml = encoding.GetString(memoryStream.ToArray()).Trim();

    // strip out the first line; we do not need it.
    xml = xml.Replace("<?xml version=\"1.0\" encoding=\"utf-8\"?>", string.Empty); 
    return xml;
}

/// De-serializer: Hydrates an object from the xml; We use UTF-8 encoding since
/// SqlServer would understand UTF-8 format only.
/// </summary>
/// <param name="xml"></param>
/// <returns></returns>
public void FromXML(string xml)
{
    // get the byte stream from the string in utf-8 encoding
    UTF8Encoding encoding = new UTF8Encoding();
    Byte[] bytes = encoding.GetBytes(xml);

    // create a stream from the bytes
    MemoryStream memoryStream = new MemoryStream(bytes);

    // create a serializer and de-serialize 'this'
    XmlSerializer serializer = new XmlSerializer(this.GetType());
    
    // finally call copy constructor to copy the deserialized output into 'this'
    this.Copy(serializer.Deserialize(memoryStream) as BusinessBase);
}

}
}

Listing 7 Using ToXML() and FromXML() functions

Book book = new Book("Visual C# 2005 A Developer's Notebook",
                     "0-596-00799-X", "Jesse Liberty");

string xml = book.ToXML(); // Serialization
Book deserializedBook = new Book();
book.FromXML(xml); //Deserialization



Listing 8 Definition of the Address and Phone classes with a partial definition of Person class

Definition of AddressType and Address	Definition of PhoneType and Phone
public enum AddressType
{
    Home = 1,
    Work = 2
}

public class Address : BusinessBase
{
    private int _addressId = -1; // default
    [XmlAttribute("AddressId")]
    public int AddessId
    {   get { return _addressId; }
        set { _addressId = value;}}
    
    private string _line1;
    [XmlAttribute("Line1")]
    public string Line1
    {   get { return _line1; }
        set { _line1 = value;}}

    private string _line2;
    [XmlAttribute("Line2")]
    public string Line2
    {   get { return _line2; }
        set { _line2 = value;}}

    private string _city;
    [XmlAttribute("City")]
    public string City
    {   get { return _city; }
        set { _city = value;}}

    private string _state;
    [XmlAttribute("State")]
    public string State
    {   get { return _state; }
        set { _state = value;}}

    private string _zipCode;
    [XmlAttribute("ZipCode")]
    public string ZipCode
    {   get { return _zipCode; }
        set { _zipCode = value;}}

    private AddressType _addrType;
    [XmlIgnore()]
    public AddressType AddrType
    {   get { return _addrType; }
        set { _addrType = value;}}
    
    [XmlAttribute("AddressTypeId")]
    public int AddressTypeId
    { get { return
            Convert.ToInt32(_addrType); }
      set {_addrType = (AddressType)value;}
    }
    
    //  default constructor
    public Address() { }
}	public enum PhoneType
{
    Home = 1,
    Work = 2,
    Mobile = 3,
 }

public class Phone : BusinessBase
{
    private int _phoneId = -1; // default
    [XmlAttribute("PhoneId")]
    public int PhoneId
    {   get { return _phoneId; }
        set { _phoneId = value;}}
    
    private int _areaCode;
    [XmlAttribute("AreaCode")]
    public int AreaCode
    {   get { return _areaCode; }
        set { _areaCode = value;}}

    private int _phoneNumber;
    [XmlAttribute("PhoneNumber")]
    public int PhoneNumner
    {   get { return _phoneNumber; }
        set { _phoneNumber = value;}}

    private PhoneType _phType;
    [XmlIgnore()]
    public PhoneType PhType
    {   get { return _phType; }
        set { _phType = value;}}

    [XmlAttribute("PhoneTypeId")]
    public PhoneType PhoneTypeId
    {   get { return _phType; }
        set { _phType = value;}}
    
    //  default constructor
    public Phone() {}
}

public class Person : BusinessBase
{   private int _personId = -1; // default
    [XmlAttribute("PersonId")]
    public int PersonId
    {   get { return _personId; }
       set { _personId = value;}}

    private List<Address> _addresses = new List<Address>();
    [XmlArrayItem(typeof(Address))]
    public List<Address> Addresses
    {   get { return _addresses; }
        set { _addresses = value;}}

    private List<Phone> _phones = new List<Phone>();
    [XmlArrayItem(typeof(Phone))]
    public List<Phone> Phones
    {   get { return _phones; }
        set { _phones = value;}}
...} 

Listing 9 Serializing Person with addresses and phones

Person person = new Person("John", "Doe");

Address addr1 = new Address();
addr1.Line1 = "124 Highland Ave.";
addr1.Line2 = "Suite 234";
addr1.City = "Lombard";
addr1.State = "IL";
addr1.ZipCode = "60148";
addr1.AddrType = AddressType.Work;

person.AddAddress(addr1);

Address addr2 = new Address();
addr2.Line1 = "3456 Main St.";
addr2.City = "Naperville";
addr2.State = "IL";
addr2.ZipCode = "60563";
addr2.AddrType = AddressType.Home;

person.AddAddress(addr2);

Phone phone1 = new Phone();
phone1.AreaCode = 800;
phone1.PhoneNumner = 1234567;
phone1.PhType = PhoneType.Work;

person.AddPhone(phone1);

Phone phone2 = new Phone();
phone2.AreaCode = 630;
phone2.PhoneNumner = 5481234;
phone2.PhType = PhoneType.Home;

person.AddPhone(phone2);
string xml = person.ToXML();
<Person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:xsd="http://www.w3.org/2001/XMLSchema" PersonId="-1" FirstName="John" LastName="Doe">
<Addresses>
  <Address AddressId="-1" Line1="124 Highland Ave." Line2="Suite 234" City="Lombard" State="IL" ZipCode="60148"
   AddressTypeId="2" /> 
  <Address AddressId="-1" Line1="3456 Main St." City="Naperville" State="IL" ZipCode="60563" AddressTypeId="1" /> 
  </Addresses>
<Phones>
  <Phone PhoneId="-1" AreaCode="800" PhoneNumber="1234567" PhoneTypeId="2" /> 
  <Phone PhoneId="-1" AreaCode="630" PhoneNumber="5481234" PhoneTypeId="1" /> 
  </Phones>
  </Person>

Listing 10 Definition of Stored procedure CreatePerson

set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
go

-- sample xml of Person object
/***
<Person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
 PersonId="-1" FirstName="John" LastName="Doe">
	<Addresses>
	  <Address AddressId="-1" Line1="124 Highland Ave." Line2="Suite 234" City="Lombard" State="IL" ZipCode="60148"
	   AddressTypeId="2" /> 
	  <Address AddressId="-1" Line1="3456 Main St." City="Naperville" State="IL" ZipCode="60563" AddressTypeId="1"
	   /> 
	</Addresses>
	<Phones>
	  <Phone PhoneId="-1" AreaCode="800" PhoneNumber="1234567" PhoneTypeId="2" /> 
	  <Phone PhoneId="-1" AreaCode="630" PhoneNumber="5481234" PhoneTypeId="1" /> 
	</Phones>
</Person>
***/

CREATE PROCEDURE [dbo].[CreatePerson]
(
	@personXML XML
)

AS
BEGIN
	-- SET NOCOUNT ON added to prevent extra result sets from
	-- interfering with SELECT statements.
	SET NOCOUNT ON;
	DECLARE @personId INT -- saves the value of the inserted Person record's Id

	BEGIN TRY --begin the TRY block

               -- wrap the multiple inserts in a Transaction
		BEGIN TRANSACTION CREATE_PERSON 

		-- insert the new person record
		INSERT INTO dbo.Person(FirstName, LastName)
		SELECT newPerson.value('@FirstName', 'varchar(50)') FirstName,
		       newPerson.value('@LastName', 'varchar(50)')  LastName
		FROM @personXML.nodes('/Person') node(newPerson)
		SET @personId = @@IDENTITY -- note down the Id of the inserted record

		-- insert records into Address table (multiple possible)
		INSERT INTO dbo.Address(PersonId, AddressTypeId, Line1, Line2, City, State, Zipcode)
		SELECT  @personId, 
			 newAddr.value('@AddressTypeId', 'int') AddressTypeId,
			 newAddr.value('@Line1', 'varchar(50)') Line1,
			 newAddr.value('@Line2', 'varchar(50)') Line2,
			 newAddr.value('@City', 'varchar(50)')  City,
			 newAddr.value('@State', 'varchar(50)') State,
			 newAddr.value('@ZipCode', 'int') Zipcode
		FROM @personXML.nodes('/Person/Addresses/Address') node(newAddr)

		-- insert records into Phone table (multiple possible)
		INSERT INTO dbo.Phone(PersonId, PhoneTypeId, AreaCode, PhoneNumber)
		SELECT @personId,
			newPhone.value('@PhoneTypeId', 'int') PhoneTypeId,
			newPhone.value('@AreaCode', 'int')	 AreaCode,
			newPhone.value('@PhoneNumber', 'int') PhoneNumber
		FROM @personXML.nodes('/Person/Phones/Phone') node(newPhone)

		-- now that all inserts have been completed, commit the transaction
		COMMIT TRANSACTION CREATE_PERSON
		
		-- return the error code followed by the Id of the inserted Person record
		SELECT ISNULL(ERROR_NUMBER(), 0) ErrorCode, @personId
		
	END TRY -- end of TRY block

	BEGIN CATCH -- control would come here only in case of an exception
		-- since an exception has ocurred, rollback the transaction
		IF @@TRANCOUNT > 0
			ROLLBACK TRANSACTION CREATE_PERSON

		-- error has ocurred; return error number and err_msg to the caller
		SELECT ISNULL(ERROR_NUMBER(), 0) ErrorCode, ERROR_MESSAGE() ErrorMessage
	END CATCH -- end of CATCH block
END -- end of SP