views:

55

answers:

3

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 object. 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 = ....

                        })
A: 

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}.

Brent Arias
Is there a way to do it without?
DDiVita
A: 

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>
Chad
Can I do it with one line?
DDiVita
@DDiVita, not the way things currently are structured. If your Xml looked different you could serialize to and from it in a line or two.
Chad
I am getting the XML from a thrid party. Thanks though!
DDiVita
+1  A: 

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.

colethecoder