Oshant
Oshant

Reputation: 178

Deserialize XML in Xamarin

I'm trying to deserialize a class named CSound

public class CSound
{ 
    public string id { get; set; }
    public string name { get; set; }
    public string file { get; set; }
    public string fav { get; set; }
}

..from this XML

<?xml version="1.0" encoding="utf-8" ?>
<ArrayOfSounds xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <CSound>
    <id>1</id>
    <name>SampleName1</name>
    <file>SampleFileName1</file>
    <fav>true</fav>
  </CSound>
  <CSound>
    <id>2</id>
    <name>SampleName2</name>
    <file>SampleFileName2</file>
    <fav>false</fav>
  </CSound>
  <CSound>
    <id>3</id>
    <name>SampleName3</name>
    <file>SampleFileName3</file>
    <fav>true</fav>
  </CSound>
  <CSound>
    <id>4</id>
    <name>SampleName4</name>
    <file>SampleFileName4</file>
    <fav>false</fav>
  </CSound>
  <CSound>
    <id>5</id>
    <name>SampleName5</name>
    <file>SampleFileName5</file>
    <fav>true</fav>
  </CSound>
</ArrayOfSounds>

T'm trying to deserialize using this section of code

   Assembly assembly = typeof(App).GetTypeInfo().Assembly;
   Stream stream = assembly.GetManifestResourceStream("SaynarSounds.Resources.XML.Sounds.xml");

   List<CSound> sounds;
   using (System.IO.StreamReader reader = new System.IO.StreamReader(stream))
   {
       XmlSerializer serializer = new XmlSerializer(typeof(List<CSound>));
       sounds = (List<CSound>)serializer.Deserialize(reader);
   }

   if (sounds == null)
   {
       sounds = new List<CSound>();
   }

   return sounds;

Find the resource and start loading, but in deserialization I get this error:

System.InvalidOperationException: There is an error in XML document.

Can you help me?

UPDATE:

the exception throw this message

[ERROR] FATAL UNHANDLED EXCEPTION: System.InvalidOperationException: There is an error in XML document. ---> System.InvalidOperationException: was not expected 02-04 12:29:58.045 E/mono-rt ( 3046): at System.Xml.Serialization.XmlSerializationReaderInterpreter.ReadRoot (System.Xml.Serialization.XmlTypeMapping rootMap) [0x0005b] in /Users/builder/data/lanes/3511/501e63ce/source/mono/mcs/class/System.XML/System.Xml.Serialization/XmlSerializationReaderInterpreter.cs:182 02-04 12:29:58.045 E/mono-rt ( 3046): at System.Xml.Serialization.XmlSerializationReaderInterpreter.ReadRoot () [0x00028] in /Users/builder/data/lanes/3511/501e63ce/source/mono/mcs/class/System.XML/System.Xml.Serialization/XmlSerializationReaderInterpreter.cs:87 02-04 12:29:58.045 E/mono-rt ( 3046): at System.Xml.Serialization.XmlSerializer.Deserialize (System.Xml.Serialization.XmlSerializationReader reader) [0x0001c] in /Users/builder/data/lanes/3511/501e63ce/source/mono/mcs/class/System.XML/System.Xml.Serialization/XmlSerializer.cs:364

But I don't have an xmlns=''.

Upvotes: 1

Views: 2554

Answers (1)

dbc
dbc

Reputation: 117284

Your problem is that if you attempt to serialize a root object of type List<CSounds> you will get XML like the following:

<ArrayOfCSound>
  <CSound>
    <id>one</id>
  </CSound>
</ArrayOfCSound>

Notice that the root element <ArrayOfX> ends in the same string X as the nested item elements <X>? This is inconsistent with your sample XML where the root element is named ArrayOfSound but the item elements are named CSound.

To work around this inconsistency, you will need to introduce a root type as follows:

[XmlRoot("ArrayOfSounds")]
public class CSoundsRoot
{
    public CSoundsRoot() { this.Sounds = new List<CSound>(); }

    [XmlElement("CSound")]
    public List<CSound> Sounds { get; set; }
}

Then do:

XmlSerializer serializer = new XmlSerializer(typeof(CSoundsRoot))
var root = (CSoundsRoot)serializer.Deserialize(reader);
var sounds = root == null ? new List<CSounds>() : root.Sounds;

As an aside, bugs in XML deserialization can often be diagosed by serializing your type and comparing the observed XML with the expected XML.

Sample fiddle.

Upvotes: 1

Related Questions