LINQtoXML nested collections and values?
I have some XML:
<Request>
<EmailAddress>string</EmailAddress>
<Item>
<name>FirstName</name>
<value>John</value>
</Item>
<Item>
<name>LastName</name>
<value>Doe</value>
</Item>
</Request>
My object:
public class TheObject{
public string EmailAddress { get; set; }
public string SkuNumber { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
I want to use LINQtoXML to pull out the FirstName and LastName values from the above XML to build the 开发者_如何学JAVAobject. How would I do this?
Update: Here is my code I started:
var object =
xml.Descendants("Request").Select(
x =>
new TheObject()
{
EmailAddress = x.Element("EmailAddress").Value.ToString(),
SkuNumber = x.Element("SKU").Value.ToString(),
FirstName = ...,
LastName = ....
})
As others have pointed out if you had control of the XML structure you could optimise it better for this type of querying. However if you are stuck with it and you want to handle it in a single LINQ to XML you could do something like the following (I've omitted null reference/exception handling for brevity depending on your schema you might want to extend this to cover these areas)
class Program
{
static void Main(string[] args)
{
var requestXml = XDocument.Parse(@"<Request>
<EmailAddress>string</EmailAddress>
<Item>
<name>FirstName</name>
<value>John</value>
</Item>
<Item>
<name>LastName</name>
<value>Doe</value>
</Item>
</Request>");
var request = (from req in requestXml.Descendants("Request")
select new TheObject
{
FirstName = (from item in req.Descendants("Item")
where item.Element("name").Value == "FirstName"
select item.Element("value").Value).First(),
LastName = (from item in req.Descendants("Item")
where item.Element("name").Value == "LastName"
select item.Element("value").Value).First(),
EmailAddress = req.Element("EmailAddress").Value
}
).First();
}
}
public class TheObject
{
public string EmailAddress { get; set; }
public string SkuNumber { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
Hope this helps with the problem.
Combine your LINQToXML with judicious use of xpath, perhaps in your projection. I don't remember the exact syntax, but your xpath would be something like:
/Request/Item/value[../name={PropertyName}]
You would substitute your "FirstName" or "LastName" for {PropertyName}.
If you don't want XPath, you can load the xml into an XElement and then get the items, eg
var requestXml = XElement.Parse(@"<Request>
<EmailAddress>string</EmailAddress>
<Item>
<name>FirstName</name>
<value>John</value>
</Item>
<Item>
<name>LastName</name>
<value>Doe</value>
</Item>
</Request>");
var firstNameItem = (from i in requestXml.Elements("Item").Where(x=>x.Element("name").Value == "FirstName")).FirstOrDefault() ?? new XElement("Item", new XElement("value", ""));
var lastNameItem = (from i in requestXml.Elements("Item").Where(x=>x.Element("name").Value == "LastName")).FirstOrDefault() ?? new XElement("Item", new XElement("value", ""));
var firstName = firstNameItem.Element("value").Value;
var lastName = lastNameItem.Element("value").Value;
Or something like that.
EDIT:
If your xml looked more like this, then you could use XmlSerializer
to go back and forth between your object and xml.
<Request>
<EmailAddress>value</EmailAddress>
<SkuNumber>value</SkuNumber>
<FirstName>value</FirstName>
<LastName>value</LastName>
</Request>
精彩评论