0

I have an xml document:

<preferences>
  <section name="PREF_SECTION_NAME_1">
    <preference name="PREF_EXAMPLE_1" type="radio">
      <default value="true"></default>
    </preference>
    <preference name="PREF_EXAMPLE_2" type="radio">
      <default value="true"></default>
    </preference>
    <preference name="PREF_EXAMPLE_3" type="radio">
       <default value="true"></default>
    </preference>
  </section>
  <section name="PREF_SECTION_NAME_2">
    <preference name="PREF_EXAMPLE_1" type="radio">
      <default value="true"></default>
    </preference>
    <preference name="PREF_EXAMPLE_2" type="radio">
      <default value="true"></default>
    </preference>
    <preference name="PREF_EXAMPLE_3" type="radio">
      <default value="true"></default>
    </preference>
  </section>
</preferences>

and I represent this in my classes:

public class Preference
{
    public string Name { get; set; }
    public bool Default { get; set; }
}

public class Section
{
    public string Name { get; set; }
    public List<Preference> Preference { get; set; }
}

public class Preferences
{
    public List<Section> Section { get; set; }
}

and I am trying to load this up in my C# method:

var xDoc = XDocument.Load("XMLFile.xml");

var sections = xDoc.Root
                  .Elements("Preferences")
                  .Select(x => new List<Section>
                  {
                    //what do I put in here?

                  })
                  .ToList();

There does not seem anything obvious to put in the bit //what do I put in here?

I have seen plenty of examples to load a non nested class this way. Is there a way to do this or?

thanks

Andrew Simpson
  • 6,883
  • 11
  • 79
  • 179
  • 1
    The pattern I've followed before is to have a factory method in each class accepting an `XElement` - and that can call others, so the `static Section FromXElement(XElement)` method would call `Preference.FromXElement` for example... see if that's enough to get you started – Jon Skeet May 18 '16 at 08:31
  • @JonSkeet thanks i will look into that – Andrew Simpson May 18 '16 at 08:31
  • @JonSkeet I was looking at one of your answers here that seemed a good way to do this http://stackoverflow.com/questions/566167/query-an-xdocument-for-elements-by-name-at-any-depth – Andrew Simpson May 18 '16 at 08:37

3 Answers3

2

This is what you want:

var preferences =
    new Preferences()
    {
        Section = xDoc.Root.Elements("section").Select(x =>
            new Section()
            {
                Name = x.Attribute("name").Value,
                Preference = x.Elements("preference").Select(y =>
                    new Preference()
                    {
                        Name = y.Attribute("name").Value,
                        Default = (bool)y.Element("default").Attribute("value"),
                    }).ToList(),
            }).ToList()
    };

That gives:

preferences

Enigmativity
  • 113,464
  • 11
  • 89
  • 172
1

You might want to do this.

var sections = xDoc.Root
                  .Descendants("section")
                  .Select(x => new Section
                  {
                     Name = x.Attribute("name").Value,
                     Preference = x.Elements("preference")
                                    .Select(y=> new Preference 
                                            {
                                                Name = (string)y.Attribute("name"),
                                                Default = (bool)y.Element("default").Attribute("value")
                                            })
                                     .ToList()
                  })
                 .ToList()

So now your (root)Preferences instance can be created using below.

var preferences = new Preferences {Section = sections };

Check this Demo

Hari Prasad
  • 16,716
  • 4
  • 21
  • 35
1
        var xDoc = XDocument.Load("sample1.xml");
        var sections = xDoc.Root.Descendants("section")
                          .Select(x => new Section
                          {
                              Name = x.Attribute("name").Value,
                              Preference = GetPreference(x)
                          }).ToList();

  private static List<Preference> GetPreference(XElement x)
    {
        return x.Descendants("preference").Select(y => new Preference
                                            {
                                                Name = y.Attribute("name").Value,
                                                Default = ConvertToBool(y.Descendants("default").FirstOrDefault().Attribute("value").Value)
                                            }).ToList();
    }

    private static bool ConvertToBool(string trueOrFalse)
    {
        return trueOrFalse == "true" ? true : false;
    }

This should help.

Pratap Bhaskar
  • 408
  • 3
  • 11