2

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

3
  • 2
    You should familiarize yourself with the XmlElement, XmlArray and XmlArrayItem attributes. The XmlSerializer apparently needs some meta info to understand what belongs where. Commented Mar 13, 2017 at 9:00
  • which elements might be repeated? all of them? just Test? Commented Mar 13, 2017 at 9:01
  • XmlArray and XmlArrayItem were the missing liks. thank you very much! Commented Mar 13, 2017 at 9:16

3 Answers 3

3

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.

Sign up to request clarification or add additional context in comments.

Comments

2

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.

1 Comment

Wow. thats pretty cool. Now i am asking myself why i was spending that much time on doing it manually -_-
1

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));

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.