.NET XmlSerializer Class

XML Serialization

Serialization is the process of persisting an object to permanent storage, like disk. It converts an object into an XML string which can then be written to disk, for example. Once serialized, it can be deserialized by another application.

Example Code

using System;
using System.Xml.Serialization;
using System.IO;
using System.Collections.Generic;

namespace XmlSerializationExample
{
	[Serializable]
	public class VehiclesExample // make sure classes are public
	{
		// can also use System.Collections.ObjectModel.ObservableCollection
		List<Vehicle> vehicles = new List<Vehicle>();

		public List<Vehicle> Vehicles
		{
			get
			{
				return vehicles;
			}
			set
			{
				if (value == vehicles)
					return;
				vehicles = value;
			}
		}

		public int NumberOfWheels { get; set; }

		[XmlAttribute] // serializer will make this an attribute
		public string Name { get; set; }

		[XmlIgnore] // serializer will ignore this property
		public string Dummy { get; set; }
	}

	public class Vehicle
	{
		public Vehicle()
		{
		}

		public Vehicle(string Maker, string Model)
		{
			this.Maker = Maker;
			this.Model = Model;
		}

		public string Maker { get; set; }
		public string Model { get; set; }
	}

	class Program
	{
		static string Serialize(VehiclesExample obj)
		{
			XmlSerializer xmlSerial = new XmlSerializer(typeof(VehiclesExample));
			using (StringWriter strWriter = new StringWriter())
			{
				xmlSerial.Serialize(strWriter, obj);
				return strWriter.GetStringBuilder().ToString();
			}
		}

		static void Main()
		{
			VehiclesExample obj = new VehiclesExample();

			obj.Name = "NAME HERE";
			obj.Dummy = "DUMMY HERE";
			obj.NumberOfWheels = 4;
			obj.Vehicles.Add(new Vehicle("Honda", "Civic"));
			obj.Vehicles.Add(new Vehicle("Honda", "Ridgeline"));
			obj.Vehicles.Add(new Vehicle("Honda", "Accord"));
			obj.Vehicles.Add(new Vehicle("Subaru", "WRX"));
			obj.Vehicles.Add(new Vehicle("Honda", "Element"));
			obj.Vehicles.Add(new Vehicle("Honda", "Pilot"));
			obj.Vehicles.Add(new Vehicle("Porsche", "911"));
			obj.Vehicles.Add(new Vehicle("Acura", "MDX"));
			obj.Vehicles.Add(new Vehicle("Honda", "CR-V"));

			string xml = Serialize(obj);

			Console.Write(xml);

			FileStream stream = new FileStream("vehices.xml", FileMode.Create);
			StreamWriter writer = new StreamWriter(stream); // this could be any type of stream
			writer.Write(xml);
			writer.Close();
			stream.Close();
		}
	}
}

The XML source produced by the serialization:

<?xml version="1.0" encoding="utf-16"?>
<VehiclesExample xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
				 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
				 Name="NAME HERE">
	<Vehicles>
	<Vehicle>
		<Maker>Honda</Maker>
		<Model>Civic</Model>
	</Vehicle>
	<Vehicle>
		<Maker>Honda</Maker>
		<Model>Ridgeline</Model>
	</Vehicle>
	<Vehicle>
		<Maker>Honda</Maker>
		<Model>Accord</Model>
	</Vehicle>
	<Vehicle>
		<Maker>Subaru</Maker>
		<Model>WRX</Model>
	</Vehicle>
	<Vehicle>
		<Maker>Honda</Maker>
		<Model>Element</Model>
	</Vehicle>
	<Vehicle>
		<Maker>Honda</Maker>
		<Model>Pilot</Model>
	</Vehicle>
	<Vehicle>
		<Maker>Porsche</Maker>
		<Model>911</Model>
	</Vehicle>
	<Vehicle>
		<Maker>Acura</Maker>
		<Model>MDX</Model>
	</Vehicle>
	<Vehicle>
		<Maker>Honda</Maker>
		<Model>CR-V</Model>
	</Vehicle>
	</Vehicles>
	<NumberOfWheels>4</NumberOfWheels>
</VehiclesExample>

XML Deserialization

Deserialization is the reverse process of serialization. XML deserialization is the process of turning an XML file or string into an object.

Example Code

using System;
using System.Xml.Serialization;
using System.IO;
using System.Collections.Generic;

namespace XmlSerializationExample
{
	[Serializable]
	public class VehiclesExample
	{
		// can also be System.Collections.ObjectModel.ObservableCollection
		List<Vehicle> vehicles = new List<Vehicle>();

		public List<Vehicle> Vehicles
		{
			get
			{
				return vehicles;
			}
			set
			{
				if (value == vehicles)
					return;
				vehicles = value;
			}
		}

		public int NumberOfWheels { get; set; }

		[XmlAttribute] // serializer will make this an attribute
		public string Name { get; set; }

		[XmlIgnore] // serializer will ignore this property
		public string Dummy { get; set; }
	}

	public class Vehicle
	{
		public Vehicle()
		{
		}

		public Vehicle(string Maker, string Model)
		{
			this.Maker = Maker;
			this.Model = Model;
		}

		public string Maker { get; set; }
		public string Model { get; set; }
	}

	class Program
	{
		public static VehiclesExample Deserialize(string xmlString)
		{
			XmlSerializer xmlSerial = new XmlSerializer(typeof(VehiclesExample));
			using (StringReader strReader = new StringReader(xmlString))
			{
				return (VehiclesExample)xmlSerial.Deserialize(strReader);
			}
		}
		public static VehiclesExample Deserialize(StreamReader xmlStream)
		{
			XmlSerializer xmlSerial = new XmlSerializer(typeof(VehiclesExample));
			return (VehiclesExample)xmlSerial.Deserialize(xmlStream);
		}

		static void Main()
		{
			FileStream stream = new FileStream("vehices.xml", FileMode.Open);
			StreamReader reader = new StreamReader(stream); // this could be any type of stream
			VehiclesExample obj;
			if (true != false) // deserialize directly from the stream, this is more efficient
			{
				obj = Deserialize(reader);
			}
			else // or if needing to deserialize a string
			{
				string xml = reader.ReadToEnd();
				obj = Deserialize(xml);
			}

			reader.Close();
			stream.Close();

			Console.WriteLine(obj.Name);
			Console.WriteLine(obj.NumberOfWheels);

			foreach(Vehicle v in obj.Vehicles)
			{
				Console.WriteLine(v.Maker + " " + v.Model);
			}
		}
	}
}

Program output:

NAME HERE
4
Honda Civic
Honda Ridgeline
Honda Accord
Subaru WRX
Honda Element
Honda Pilot
Porsche 911
Acura MDX
Honda CR-V

A More Complex Example

<?xml version="1.0" encoding="UTF-8"?>
<shoppingTheWeb xmlns="http://www.searchwebsiteshoppingexample.com/api/search/v1">
	<version>1.0</version>
	<timestamp>2017-01-01T12:00:00.000Z</timestamp>
	<searchItems count="3">
		<item>
			<itemId>8765678987654323443234567878987</itemId>
			<title>item #1 title</title>
			<category>
				<catId>1011</catId>
				<catName>Stuff</catName>
			</category>
			<status>
				<available>true</available>
				<price priceId="USD">123.45</price>
				<quantity>2343</quantity>
			</status>
		</item>
		<item>
			<itemId>1234567899874532345678987987351</itemId>
			<title>item #2 title</title>
			<category>
				<catId>1022</catId>
				<catName>Junk</catName>
			</category>
			<status>
				<available>true</available>
				<price priceId="USD">45.67</price> <!-- must access the attribute and element -->
				<quantity>45</quantity>
			</status>
		</item>
		<item>
			<itemId>9856928734621987689731628934465</itemId>
			<title>item #3 title</title>
		</item>
	</searchItems>
</shoppingTheWeb>

Now, deserialize the above XML file named "example.xml" and save the results to a flat text file named "data.txt"

using System;
using System.Collections.Generic;
using System.Xml.Serialization;
using System.IO;

namespace ConsoleApp1
{
	[XmlRoot("shoppingTheWeb", Namespace = "http://www.searchwebsiteshoppingexample.com/api/search/v1")]
	public class ShoppingResults
	{
		public double version { get; set; }
		public DateTime timestamp { get; set; }
		public SearchItems searchItems { get; set; }

		public static ShoppingResults Deserialize(string xml)
		{
			XmlSerializer xmlSerial = new XmlSerializer(typeof(ShoppingResults));
			using (StringReader strReader = new StringReader(xml))
			{
				return (ShoppingResults)xmlSerial.Deserialize(strReader);
			}
		}
		public static ShoppingResults Deserialize(StreamReader xmlStream)
		{
			XmlSerializer xmlSerial = new XmlSerializer(typeof(ShoppingResults));
			return (ShoppingResults)xmlSerial.Deserialize(xmlStream);
		}
	}

	public class SearchItems
	{
		[XmlAttribute("count")]
		public int count { get; set; }
		[XmlElement("item")] // this tells the deserializer that the item tag is used
		public List<Item> items { get; set; }
	}

	public class Item
	{
		public string itemId { get; set; }
		public string title { get; set; }
		public Category category { get; set; }
		public Status status { get; set; }
	}

	public class Category
	{
		public int catId { get; set; }
		public string catName { get; set; }
	}

	public class Status
	{
		public bool available { get; set; }
		public Price price { get; set; }
		public int quantity { get; set; }
	}

	public class Price
	{
		[XmlAttribute]
		public string priceId { get; set; }
		[XmlText] // this is new to this tutorial and it allows for access to the price's inner text/value
		public double InnerText { get; set; }
	}

	class Program
	{
		static void Main(string[] args)
		{
			using (TextWriter txt = new StreamWriter("data.txt", false))
			{
				ShoppingResults shopping;
				using (StreamReader reader = new StreamReader("example.xml"))
				{
					shopping = ShoppingResults.Deserialize(reader);
				}
				txt.WriteLine(shopping.timestamp + "\r\nITEMID\tTITLE\tCATID\tCATNAME\tAVAILABLE\tPRICE\tPRICEID\tQUANTITY\r\n");
				foreach(Item item in shopping.searchItems.items)
					txt.WriteLine(item.itemId + '\t' + item.title + '\t' + item.category?.catId + '\t' + item.category?.catName + '\t' + item.status?.available + '\t' + item.status?.price?.InnerText + '\t' + item.status?.price?.priceId + '\t' + item.status?.quantity + "\r\n");
			}
		}
	}
}

The tab seperated output from the following code will look like this:

1/1/2017 12:00:00 PM
ITEMID	TITLE	CATID	CATNAME	AVAILABLE	PRICE	PRICEID	QUANTITY

8765678987654323443234567878987	item #1 title	1011	Stuff	True	123.45	USD	2343

1234567899874532345678987987351	item #2 title	1022	Junk	True	45.67	USD	45

9856928734621987689731628934465	item #3 title