The code for this post is here: https://github.com/Corey255A1/WunderVisionMiscCode/tree/master/XmlReadNWrite
Let’s start with defining our data structure. I went with the classic Class/Student type example.
<?xml version="1.0"?> <Classes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <Class name="History" time="0700"> <Students> <Student firstname="Joanna" lastname="Johnson" studentid="556825" /> <Student firstname="Frederick" lastname="Lemowitz" studentid="567864" /> </Students> </Class> <Class name="Mathematics" time="0800"> <Students> <Student firstname="Bobby" lastname="Villanova" studentid="568845" /> <Student firstname="Sandra" lastname="Thomson" studentid="574568" /> </Students> </Class> </Classes>
So in our code we will start off like this:
using System.Xml.Serialization;namespace XmlReadNWrite { [XmlRoot(“Classes”)] public class StudentListFile { [XmlElement(“Class”)] public List<Class> Classes { get; set; } }
Be sure to add the System.Xml.Serialization namespace. We will define our XMLRoot attribute. This is where the serializer will start taking the data from the XML and matching it up to the class structure. It is important that the letter capitalization and spelling matches what your XML file looks like.
Now looking at our XML structure, we want to have multiple Class elements, so you can see in our code we have a List
public class Class { [XmlAttribute("name")] public string Name { get; set; }[XmlAttribute(“time”)] public string Time { get; set; }
[XmlArray(“Students”), XmlArrayItem(“Student”)] public List<Student> Students { get; set; } }
If we look back at our XML we notice the the Class element has two Attributes, “name” and “time”. In our Class class then we add two strings, with the XmlAttribute attribute ensuring the spelling and capitalization matches the XML. Now, here I have Time just defined as a simple string, however there ways to get more complex data types to serialize other than just string. In this post I just cover basic datatypes.
Each class has a Students element that is populated with a List of students. I could have created a Students class that has a list of Student as a property however, since we know that Students only contains a list of Student, we can short cut it with the [XmlArray(“Students”), XmlArrayItem(“Student”)] attribute.
Now we define our Student.
public class Student { [XmlAttribute("firstname")] public string FirstName { get; set; }[XmlAttribute(“lastname”)] public string LastName { get; set; }
[XmlAttribute(“studentid”)] public int StudentID { get; set; } }
Like before we have our XmlAttributes defined, and you can see here we have StudentID defined as an int. There is no other special code needed for things like int, double or float.
That defines our XML structure in C# code.
Now for the Reading and Writing. The code to read and write an XML file is always the same, and I find convenient to just make the Read and Write a static template function and just call that with the Class I want to read or write.
public static T ReadXML<T>(string filePath) { try { using (FileStream stream = new FileStream(filePath, FileMode.Open)) { var xsz = new XmlSerializer(typeof(T)); return (T)xsz.Deserialize(stream); } } catch (Exception e) { Console.WriteLine(e.ToString()); } return default; }public static bool WriteXML<T>(T classToSave, string filePath) { try { using (FileStream stream = new FileStream(filePath, FileMode.Create)) { var xsz = new XmlSerializer(typeof(T)); xsz.Serialize(stream, classToSave); } return true; } catch (Exception e) { Console.WriteLine(e.ToString()); return false; }
}
And with those two functions, you can read and write any XML file that is defined the way we did it above! XmlSerializer lives in the same System.Xml.Serialization namespace. Basically get a file stream, create the Serializer based on the class type, and call Serialize or Deserialize!
Now for the test code.
static void Main(string[] args) { StudentListFile slf = new StudentListFile(); slf.Classes = new List<Class>() { new Class() { Name = "History", Time = "0700", Students = new List<Student>() { new Student(){FirstName="Joanna", LastName="Johnson", StudentID=556825}, new Student(){FirstName="Frederick", LastName="Lemowitz", StudentID=567864} } }, new Class() { Name = "Mathematics", Time = "0800", Students = new List<Student>() { new Student(){FirstName="Bobby", LastName="Villanova", StudentID=568845}, new Student(){FirstName="Sandra", LastName="Thomson", StudentID=574568} } } };Console.WriteLine(<span style="background-color: #fff0f0">"Writing out Class List..."</span>); XmlUtils.WriteXML(slf, <span style="background-color: #fff0f0">"StudentList.xml"</span>); Console.WriteLine(<span style="background-color: #fff0f0">"Reading in Class List..."</span>); StudentListFile readFile = XmlUtils.ReadXML<StudentListFile>(<span style="background-color: #fff0f0">"StudentList.xml"</span>); <span style="color: #008800; font-weight: bold">foreach</span>(Class c <span style="color: #008800; font-weight: bold">in</span> readFile.Classes) { Console.WriteLine(<span style="color: #FF0000; background-color: #FFAAAA">$</span><span style="background-color: #fff0f0">"Class {c.Name} at {c.Time}"</span>); <span style="color: #008800; font-weight: bold">foreach</span>(Student s <span style="color: #008800; font-weight: bold">in</span> c.Students) { Console.WriteLine(<span style="color: #FF0000; background-color: #FFAAAA">$</span><span style="background-color: #fff0f0">"- Student {s.FirstName} {s.LastName} ID:{s.StudentID}"</span>); } }
}
We create our StudentListFile class and the create a new List
*I think it is important to note that doing the {} syntax to set the values of a new class() property, the values are set after the constructor has been called. So if something in the constructor depends on one of the values being set, it won’t be until after it is complete. So if there is value that needs to be set during construction, make sure to pass it in rather than use the {} syntax.*
Then Write out the XML file… Read it back in and print it out to the console!
And that is it! A very simple way to read and write XML files using C#.