Reputation: 73
I am trying to deserialize a Xml File using the XmlSerializer. A part of my file looks like this:
<bla>
<ListOfListOfTest>
<ListOfTest>
<Test>
</Test>
</ListOfTest>
</ListOfListOfTest>
</bla>
I tried different ways but it does not work.
My first try looked like:
public class bla
{
public bla()
{
ListOfListOfTest = new List<List<Test>>();
}
[...]
public List<List<Test>> ListOfListOfTest{ get; set; }
}
-> does not work.
Second try:
public class bla
{
public bla()
{
ListOfListOfTest = new List<List<Test>>();
}
[..]
public List<List<Test>> ListOfListOfTest { get; set; }
[XmlArrayItemAttribute]
public List<List<Test>> listOfListOfTest { get { return ListOfListOfTest ; } }
}
-> failed as well
Third try:
public class bla
{
public bla()
{
ListOfListOfTest = new List<Foo>();
}
[...]
public List<Foo> ListOfListOfTest { get; set; }
}
public class Foo
{
public Foo()
{
ListOfTest = new List<Test>();
}
public List<Test> ListOfTest { get; set; }
}
-> failed...
Failed means that the XmlSerializer
does not fill the List
during serializer.Deserialize()
.
I´m always getting a List
with zero Elements in it.
What am i doing wrong?
thanks for your effort
Upvotes: 2
Views: 2272
Reputation: 236248
Visual Studio has a handy option - you should just copy-paste your xml and go to menu Edit > Paste Special > Paste XML As Classes. And Visual Studio will generate classes which you can use to serialize/deserialize your xml. In this particular case it will generate:
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
public partial class bla
{
private blaListOfListOfTest listOfListOfTestField;
public blaListOfListOfTest ListOfListOfTest
{
get { return this.listOfListOfTestField; }
set { this.listOfListOfTestField = value; }
}
}
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class blaListOfListOfTest
{
private blaListOfListOfTestListOfTest listOfTestField;
public blaListOfListOfTestListOfTest ListOfTest
{
get { return this.listOfTestField; }
set { this.listOfTestField = value; }
}
}
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class blaListOfListOfTestListOfTest
{
private object testField;
public object Test
{
get { return this.testField; }
set { this.testField = value; }
}
}
You can do some adjustments after that - e.g. remove type qualifiers or replace properties with auto-properties (which can be done with visual studio extensions). After few keystrokes:
[Serializable]
[DesignerCategory("code")]
[XmlType(AnonymousType = true)]
[XmlRoot(Namespace = "", IsNullable = false)]
public partial class bla
{
public blaListOfListOfTest ListOfListOfTest { get; set; }
}
[Serializable]
[DesignerCategory("code")]
[XmlType(AnonymousType = true)]
public partial class blaListOfListOfTest
{
public blaListOfListOfTestListOfTest ListOfTest { get; set; }
}
[Serializable]
[DesignerCategory("code")]
[XmlType(AnonymousType = true)]
public partial class blaListOfListOfTestListOfTest
{
public object Test { get; set; }
}
And deserialization will look like:
var serializer = new XmlSerializer(typeof(bla));
var blaObj = serializer.Deserialize(new StringReader(xmlString));
Upvotes: 1
Reputation: 378
To get to grips with how the XML will look when correctly deserialized, copy your XML:
<bla>
<ListOfListOfTest>
<ListOfTest>
<Test>
</Test>
</ListOfTest>
</ListOfListOfTest>
</bla>
Create a class in C#. Click "Edit" at the top, then "Paste Special" then "Paste XML As Classes" while your cursor is inside the class. Visual Studio will correctly deserialize the XML for you and create the necessary classes. Use this to compare what you thought you needed, and what you actually need, in order to clarify for yourself how deserialization should work.
Upvotes: 2
Reputation: 1062915
Something like this?
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml.Serialization;
class Program {
static void Main() {
var xml = @"<bla>
<ListOfListOfTest>
<ListOfTest>
<Test>
</Test>
</ListOfTest>
</ListOfListOfTest>
</bla>";
var bar = (Bar)new XmlSerializer(typeof(Bar)).Deserialize(new StringReader(xml));
Console.WriteLine(bar.Lists.Sum(_ => _.Items.Count)); // 1
}
}
[XmlRoot("bla")]
public class Bar {
[XmlArray("ListOfListOfTest")]
[XmlArrayItem("ListOfTest")]
public List<Foo> Lists { get; } = new List<Foo>();
}
public class Foo {
[XmlElement("Test")]
public List<Test> Items { get; } = new List<Test>();
}
public class Test { }
The actual layout depends on which elements might be duplicated, and whether you need to be able to reproduce the exact organisation (vs just wanting all the Test
items). In the code above, ListOfListOfTest
is not expected to be duplicated, but there can be any number of ListOfTest
or Test
elements.
Upvotes: 3