views:

405

answers:

6

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.

A: 

Xstream for .Net could be a useful API

Sri Kumar
+3  A: 

That isn't valid Xml. There needs to be a core root element for it to work properly.

ck
The XML output from a hardware device. I was hoping there was an elegant way to deal with it.
Brian Chavez
+3  A: 

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"&gt;
    <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.

astander
The problem is, the XML output is from a hardware device. So, I can't control the output. I need to parse it as is. I was hoping there'd be an elegant way of doing it. =/
Brian Chavez
Perhaps, every time you receive XML, you can wrap it with some root element, and then use XmlDocument to parse it.
ironic
Thanks, I've submitted a Firmware bug with the manufacture of the hardware device. Hopefully, they'll fix the problem.
Brian Chavez
+1  A: 

As the other posters say, this XML that the hardware device produces is not compatible to the way .NET serializes/deserializes object. Valid XML, and .NET requires valid XML, has a root element.

I suggest:

  • either you modify your obtained XML to match the way astander presents in his xml code snippet.
  • or you write a simple xml parser for your file that deserializes the file like you need

br, Marcel

Marcel
+3  A: 

this is not a valid xml so you can not deserialize it like a valid xml. You need some kind of hack to make this work. i'd suggest to insert at beginning of the xml and inserting at the end of xml. then you can deserialize it, since you cant make this change at xml side, do it in your code.

String ss; 
// lets assume this holds your xml data in string.
ss.append("</ArrayOfFoo>");
ss.replace("<?xml version=\"1.0\" encoding=\"utf-16\"?>", "<?xml version=\"1.0\" encoding=\"utf-16\"?> <ArrayOfFoo>")

var s2 = new XmlSerializer(typeof(List<Foo>));
StringReader sr = new StringReader(ss);
List<Foo> returnList = (List<Foo>)s2.Deserialize(sr);

now this shall return you the correct list.

Numenor
+1  A: 

Technically, what you have there is not a well-formed XML document (which has exactly one root element), but rather an well-formed external parsed entity (which can have any number of elements not contained in other elements, as well as text not contained in any elements). Therefore, it should parse if your XML parser has an entry point for parsing EPEs rather than documents. You could also create a stub document which includes by reference your EPE and parse that document.

Kevin Reid