tags:

views:

105

answers:

2

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

A: 

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
        })
}
Kirk Broadhurst
A: 

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>";
Metro Smurf