creating composite objects with linq to xml
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").ValueOrDefau开发者_运维知识库lt(),
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
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
})
}
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>";
精彩评论