22

I'm trying to deserialize the following file:

<league>
    <players>
        <skater>
            <name>Wayne Stamkos</name>
            <goals>23</goals>
            <assists>34</assists>
        </skater>
        <skater>
            <name>Sidney Lindros</name>
            <goals>41</goals>
            <assists>44</assists>
        </skater>
        <goalie>
            <name>Martin Roy</name>
            <wins>15</wins>
            <losses>12</losses>
        </goalie>
        <skater>
            <name>Paul Forsberg</name>
            <goals>21</goals>
            <assists>51</assists>
        </skater>
        <goalie>
            <name>Roberto Rinne</name>
            <wins>18</wins>
            <losses>23</losses>
        </goalie>
    </players>
</league>

With the following code:

namespace ConsoleApplication2
{
    [XmlRoot("league")]
    public class League
    {
        [XmlArray("players")]
        [XmlArrayItem("skater")]
        public List<Skater> skaters { get; set; }
        [XmlArrayItem("goalie")]
        public List<Goalie> goalies { get; set; }
    }

    public class Skater
    {
        [XmlElement("name")]
        public string Name;
        [XmlElement("goals")]
        public int Goals;
        [XmlElement("assists")]
        public int Assists;
    }

    public class Goalie
    {
        [XmlElement("name")]
        public string Name;
        [XmlElement("wins")]
        public int Wins;
        [XmlElement("losses")]
        public int Losses;
    }

    class Program
    {
        static void Main(string[] args)
        {
            using (FileStream reader = new FileStream(@"C:\Temp\test.xml", FileMode.Open, FileAccess.Read))
            {
                var ser = new XmlSerializer(typeof(League));
                League league = (League)ser.Deserialize(reader);
            }
        }
    }
}

I'm expecting to get back a League object containing a Skaters list with 3 elements and a Goalies list with 2 elements. I do get the expected Skaters list but the Goalies list is empty. What am I doing wrong?

3
  • 1
    you need an interface common to Goalie and Skater, then you can have a single array of these. Commented Nov 21, 2013 at 22:12
  • @Marc Gravell: The file can contain 0 to N goalies and skaters. Commented Nov 21, 2013 at 22:28
  • @ChrisB d'oh; if I used my eyes I could have answered that myself ;p Commented Nov 21, 2013 at 22:32

1 Answer 1

39

There are two ways to do this; the first is to do something like:

[XmlArray("players")]
[XmlArrayItem("skater", Type=typeof(Skater))]
[XmlArrayItem("goalie", Type=typeof(Goalie))]
public List<SomeCommonBaseClass> Players { get; set; }

which maps the two element types inside a single collection. Worst case, SomeCommonBaseClass could be object:

[XmlArray("players")]
[XmlArrayItem("skater", Type=typeof(Skater))]
[XmlArrayItem("goalie", Type=typeof(Goalie))]
public List<object> Players { get; set; }

The second is to make <players> map to a wrapper object:

[XmlElement("players")]
public Players Players { get;set;}
...
public class Players
{
    [XmlElement("skater")]
    public List<Skater> Skaters {get;set;}

    [XmlElement("goalie")]
    public List<Goalie> Goalies {get;set;}
}

Which to choose depends on the circumstance; the latter allows things like "at most one goalie", by changing it to:

    [XmlElement("goalie")]
    public Goalie Goalie {get;set;}
Sign up to request clarification or add additional context in comments.

2 Comments

Since I really need 2 separate lists, solution 2 seems to be my only alternative. Thanks!
The second solution is a very elegant way to accomplish that. +1

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.