Tutorial :creating composite objects with linq to xml



Question:

I have a simple xml doc I am reading, a sample is here:

<people>    <person>      <name>joe</name>      <age>21</age>      <contact>        <phone-nums>          <phone-num>            <number>123-4567</number>            <type>home</type>          </phone-num>          <phone-num>            <number>123-4567</number>            <type>office</type>          </phone-num>        </phone-nums>      </contact>    </person>  </people>  

I read it in using HttpContent.ReadAsXElement() and then use Linq to create objects. My simple objects look something like this:

public class PeopleList : List<Person> { }    public class Person  {      public string name;      public int age;      public Contact contact;  }    public class Contact  {     public PhoneList phones;  }    public class PhoneList : List<Phone>{}    public class Phone  {      public string number;      public string type;  }  

Ok, so now I have my class that reads it all in which is where I am getting hung up (it's an extension method in my code):

public PeopleList ReadAsPeopleList(this HttpContent content)      {          var people = content.ReadAsXElement();            var personQuery = from p in people.Elements("person")              select new Person()              {                  name = p.Element("name").ValueOrDefault(),                  age = p.Element("age").ValueOrDefault(),                  contact = (from c in p.Elements("contact")                      select new Contact()                      {                           //I don't know how to select a new list of phones into a contact here                      }              };            PeopleList l = new PeopleList();          l.AddRange(personQuery);          return l;      }  

I'm having trouble creating the contact type with the composite phone number list. Any help would be appreciated.

Note: I rewrote a simplified version of all of this here so


Solution:1

To get the collection of 'Phone' that needs to go in the contact, you could use this:

c.Elements("phone-num").Select(phone => new Phone()      {          number = phone.Element("number").Value,          type = phone.Element("type").Value      });  

so you want

select new Contact()   {       PhoneList = c.Elements("phone-num").Select(phone => new Phone()          {              number = phone.Element("number").Value,              type = phone.Element("type").Value          })  }  


Solution:2

This answer will be a bit skewed from your actual question, but may provide some direction to your eventual solution.

Consider using a List<T> for your collections rather than creating a BusinessObjectCollection : List<T>. Here's a good SO read that may be of interest: List or BusinessObjectCollection?

With that being said, this is a somewhat tweaked version of your classes; I've used properties instead of fields as well. And finally, since I've not worked with HTTPContext much, I thew together an example using a basic string. The method presented here should be easy enough to convert into an extension method for HTTPContext, though:

public static IEnumerable<Person> ReadAsPeopleList( string xml )  {      var doc = XDocument.Parse( xml );        var people = doc.Root.Elements( "person" )          .Select( x => new Person          {              Name = x.Element( "name" ).Value,              Age = int.Parse( x.Element( "age" ).Value ),              Contact = new Contact              {                  Phones = x.Descendants( "phone-num" )                  .Select( p => new Phone                  {                      Number = p.Element( "number" ).Value,                      Type = p.Element( "type" ).Value                  } )              }          }          );        return people;  }    private static string MyXml = @"  <people><person><name>joe</name><age>21</age><contact><phone-nums>  <phone-num><number>123-4567</number><type>home</type></phone-num>  <phone-num><number>123-4567</number><type>office</type></phone-num>  </phone-nums></contact></person><person><name>bill</name><age>30</age>  <contact><phone-nums><phone-num><number>123-4567</number><type>home</type>  </phone-num><phone-num><number>123-4567</number><type>office</type>  </phone-num></phone-nums></contact></person></people>";  

Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »