Slimper Slimper - 3 months ago 37
C# Question

Deserializing Xml to List<T> - xmlns='' was not expected

I have problems with deserializing XML to the List of locations objects.

Given the following XML:

<?xml version="1.0" encoding="utf-8"?>
<locations>
<location id="1">
<level name="3" complete="True" stars="1" firstMisson="True" secondMission="False" thridMission="False" />
</location>
<location id="2">
<level name="4" complete="True" stars="3" firstMisson="True" secondMission="True" thridMission="True" />
</location>
</locations>


And the following class:

[System.Serializable]
[XmlRoot(ElementName = "level")]
public class Level
{
[XmlAttribute(AttributeName = "name")]
public string Name { get; set; }
[XmlAttribute(AttributeName = "complete")]
public string Complete { get; set; }
[XmlAttribute(AttributeName = "stars")]
public string Stars { get; set; }
[XmlAttribute(AttributeName = "firstMisson")]
public string FirstMisson { get; set; }
[XmlAttribute(AttributeName = "secondMission")]
public string SecondMission { get; set; }
[XmlAttribute(AttributeName = "thridMission")]
public string ThridMission { get; set; }
}
[System.Serializable]
[XmlRoot(ElementName = "location")]
public class Location
{
[XmlElement(ElementName = "level")]
public Level Level { get; set; }
[XmlAttribute(AttributeName = "id")]
public string Id { get; set; }
}
[System.Serializable]
[XmlRoot(ElementName = "locations")]
public class Locations
{
[XmlElement(ElementName = "location")]
public Location Location { get; set; }

public List<Locations> LocDb = new List<Locations>();
}
[System.Serializable]
[XmlRoot(ElementName = "xml")]
public class Xml
{
[XmlElement(ElementName = "locations")]
public Locations Locations { get; set; }
}


Deserialization Method

public List<Locations> locDB = new List<Locations>();

public static void LoadData()
{
string filepath = Application.dataPath + @"/XML/GameXMLdata.xml";

var xmlSerializer = new XmlSerializer(locDB.GetType());
var stream = File.Open(filepath, FileMode.Open);


locDB = (List<Locations>)xmlSerializer.Deserialize(stream);//locations xmlns=''> was not expected

stream.Close();

Debug.Log(locDB[1].Location.Id);

}


So how do I deserialize XML to List of location objects?

Many thanks for help.

Answer

You need only two classes:

[XmlType("level")]
public class Level
{
    [XmlAttribute("name")]
    public string Name { get; set; }
    [XmlAttribute("complete")]
    public string Complete { get; set; }
    [XmlAttribute("stars")]
    public string Stars { get; set; }
    [XmlAttribute("firstMisson")]
    public string FirstMisson { get; set; }
    [XmlAttribute("secondMission")]
    public string SecondMission { get; set; }
    [XmlAttribute("thridMission")]
    public string ThridMission { get; set; }
}

[XmlType("location")]
public class Location
{
    [XmlElement("level")]
    public Level Level { get; set; }
    [XmlAttribute("id")]
    public string Id { get; set; }
}

The important is to apply XmlType attribute to the class Location rather than XmlRoot.

Now you can deserialize your XML to List<Location> like this:

var xmlSerializer = new XmlSerializer(typeof(List<Location>), 
    new XmlRootAttribute("locations"));
List<Location> locations;
using (var stream = File.OpenRead(filepath))
    locations = (List<Location>)xmlSerializer.Deserialize(stream);

The trick is to specify the root element name ("locations" in your case) using the XmlSerializer(Type, XmlRootAttribute) constructor overload.