Search code examples
c#serializationxml-serializationxmlroot

XmlSerializer Deserializing Array/List of Multiple Objects at Root


I'm trying to deserialize the following XML output:

<?xml version="1.0" encoding="ISO-8859-1"?>
<Foo>
   <Val>Data1</Val>
</Foo>
<Foo>
   <Val>Data2</Val>
</Foo>

(This is output from a hardware device, and cannot be changed)

I have an XML type defined as:

    [XmlType(AnonymousType=true, Namespace="")]
    public class Foo
    {
        public string Val { get; set; }
    }

I've tried to deserialize this array by creating a serializer like:

  var s = new XmlSerializer(typeof(Foo[]));
  //or
  var s = new XmlSerializer(typeof(List<Foo>);

But every call to s.Deserialize() causes an InvalidOperaitonException:

 System.InvalidOperationException: <Foo xmlns=''> was not expected.

Note

 var s = new XmlSerializer(typeof(Foo));
 // Only deseralizes the first Foo (Data1).

Thanks for your help.


Solution

  • I think the issue is with your provided xml.

    Test app says

    List<Foo> list = new List<Foo> {new Foo {Val = "Data1"}, new Foo {Val = "Data2"}};
    var s = new XmlSerializer(typeof(List<Foo>));
    StringBuilder sb = new StringBuilder();
    XmlWriter wr = XmlWriter.Create(sb);
    s.Serialize(wr, list);
    
    string ss = sb.ToString();
    
    var s2 = new XmlSerializer(typeof(List<Foo>));
    StringReader sr = new StringReader(ss);
    List<Foo> returnList = (List<Foo>)s2.Deserialize(sr);
    

    And the XML should be

    <?xml version="1.0" encoding="utf-16"?>
    <ArrayOfFoo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <Foo>
            <Val>Data1</Val>
        </Foo>
        <Foo>
            <Val>Data2</Val>
        </Foo>
    </ArrayOfFoo>
    

    If you can remove the inital line

    <?xml version="1.0" encoding="ISO-8859-1"?>
    

    And minipulate the string into

    string s = "<ArrayOfFoo><Foo>   <Val>Data1</Val></Foo><Foo>   <Val>Data2</Val></Foo></ArrayOfFoo>";
    var s2 = new XmlSerializer(typeof(List<Foo>));
    StringReader sr = new StringReader(s);
    List<Foo> list = (List<Foo>)s2.Deserialize(sr);
    

    That could work.