3

I feel like I am going made. I have written a hundred deserializing routines, but this one is killing me!

Below is what I get returned from a service. A very simple array of strings...I think.

<ArrayOfstring xmlns="http://schemas.microsoft.com/2003/10/Serialization/Arrays" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
    <string>Action &amp; Adventure</string>
    <string>Comedy</string>
    <string>Drama</string>
    <string>Family</string>
    <string>Horror</string>
    <string>Independent &amp; World</string>
    <string>Romance</string>
    <string>Sci-Fi/Fantasy</string>
    <string>Thriller &amp; Crime</string>
</ArrayOfstring>

I am using out the box deserializing

var serializer = new XmlSerializer(typeof(List<string>));
var reader = new StringReader(xmlString);
var GenreList = (List<string>)serializer.Deserialize(reader);

but I get the following error on the Deserialize line:

<ArrayOfstring xmlns='http://schemas.microsoft.com/2003/10/Serialization/Arrays'> was not expected

I have tried including the namespace and creating all manner of exotic objects in an attempt to get this to work. Crazy amount of time. In the end I have requested it in JSON and deserialised that with Json.net.

However I am curious as to what I have been doing wrong!

jessehouwing
  • 106,458
  • 22
  • 256
  • 341
NER1808
  • 1,829
  • 2
  • 33
  • 45

5 Answers5

5

Of course XmlSerializer can deserialize it. All you need is to create XmlSerializer as follows

var serializer = new XmlSerializer(typeof(List<string>), 
                                   new XmlRootAttribute() { ElementName = "ArrayOfstring", Namespace = "http://schemas.microsoft.com/2003/10/Serialization/Arrays" });
I4V
  • 34,891
  • 6
  • 67
  • 79
4

The XML Serializer cannot deserialize a simpletype or a list of simple types without additional specification, but the DataContractReader can:

        string content = @"
        <ArrayOfstring xmlns=""http://schemas.microsoft.com/2003/10/Serialization/Arrays"" xmlns:i=""http://www.w3.org/2001/XMLSchema-instance"">
            <string>Action &amp; Adventure</string>
            <string>Comedy</string>
            <string>Drama</string>
            <string>Family</string>
            <string>Horror</string>
            <string>Independent &amp; World</string>
            <string>Romance</string>
            <string>Sci-Fi/Fantasy</string>
            <string>Thriller &amp; Crime</string>
        </ArrayOfstring>";

        var serializer = new DataContractSerializer(typeof(string[]));
        var reader = new XmlTextReader(new StringReader(content));
        var GenreList = new List<string>((string[])serializer.ReadObject(reader));
jessehouwing
  • 106,458
  • 22
  • 256
  • 341
  • -1 `The XML Serializer cannot deserialize a simpletype or a list of simple types` I wouldn't speak so sure. (BTW: My downvote is only for the false statement regarding the future readers, If you remove it and explain only DataContractReader, I will undo my downvote) – I4V May 14 '13 at 20:23
  • Updated the statement. Without adding a root element, specifying namespaces or other 'tricks' it doesn't. – jessehouwing May 15 '13 at 17:40
  • where does one find the DataContractSerializer? – ecoe Dec 15 '14 at 23:31
  • http://msdn.microsoft.com/en-us/library/system.runtime.serialization.datacontractserializer%28v=vs.110%29.aspx – jessehouwing Dec 16 '14 at 08:43
0

You can also use a simple class to achieve the same results. Note that I removed the namespaces from your XML file for brevity. You can implement reading of the namespaces in the serializer if you please.

    public class ArrayOfstring
    {
        [XmlElement("string")]
        public List<string> strings;
    }

    private void Deserialize(string xmlString)
    {
        var serializer = new XmlSerializer(typeof(ArrayOfstring));
        var reader = new StringReader(xmlString);
        var GenreList = ((ArrayOfstring) serializer.Deserialize(reader)).strings;
    }
Wooster11
  • 179
  • 5
  • I tried this and it still failed. [XmlRoot] public class ArrayOfstring { [XmlElement("string")] public string[] Strings { get; set; } } – NER1808 May 16 '13 at 18:06
0

This will work

DataContractSerializer xmlSer = new DataContractSerializer(typeof(string[]));
TextReader reader=new StreamReader(xmlString);
var stringArr= (string[])xmlSer.ReadObject(reader);
List<string> listStr=new List<>();
for(var s in stringArr)
{
listStr.Add(s);
}
sarawgeek
  • 451
  • 6
  • 10
0

I realize this is an old question, but I recently ran on to the same issue and wanted to share what worked for me. I tried all the approaches outlined as potential solutions, but couldn't get any of them to work. Even specifying the namespace in the XmlRootAttribute approach would throw the "was not expected" error reported in the original problem. I was getting the ArrayOfString as a response from an API, so I used an XDocument parse approach:

List<string> lstGenre = new List<string>();
var response = await client.PostAsync(url, content);
var responseString = await response.Content.ReadAsStringAsync();

XDocument xdoc = XDocument.Parse(responseString);
XNamespace ns = xdoc.Root.GetDefaultNamespace();
XElement root = xdoc.Element(XName.Get("ArrayOfString", ns.NamespaceName));
IEnumerable<XElement> list = root.Elements();
foreach (XElement element in list)
{
    string item = element.Value;  // <-- individual strings from the "ArrayOfString"
    lstGenre.Add(item);
}
littleGreenDude
  • 301
  • 2
  • 4
  • 14