views:

1514

answers:

3

Let's say I have the following XML:

<Account>
        <AccountExpirationDate>6/1/2009</AccountExpirationDate>
</Account>

I want to use LINQ to XML to parse this into an object I'll call Account:

public class Account {
    public DateTime? AccountExpirationDate { get; set; }
}

This is the C# code I've tried, but it won't let me use null:

var accountSettings = 
  from settings in templateXML.Descendants("Account")
  select new Account {
      AccountExpirationDate =   
         string.IsNullOrEmpty(settings.Element("AccountExpirationDate").Value) 
         ? DateTime.Parse(settings.Element("AccountExpirationDate").Value) 
         : null
  };

Is there a way for me to only assign AccountExpiration a date if the element exists in the XML? In my business logic it is acceptable for the value to be null. Thanks!

+1  A: 
var accountSettings =
  from settings in templateXML.Descendants("Account")
  select new Account {
    AccountExpirationDate = 
      string.IsNullOrEmpty((string)settings.Element("AccountExpirationDate")) 
            ? (DateTime?)null
            : DateTime.Parse(settings.Element("AccountExpirationDate").Value) 
  };
Mehrdad Afshari
This throws an exception when the AccountExpirationDate element is empty: System.FormatException: String was not recognized as a valid DateTime
Andy May
@Andy May: you said about the element existing or not... you didn't say about it being empty...
Marc Gravell
Andy: Updated the answer. Your original snippet didn't use `string.IsNullOrEmpty` correctly and I had blindly copied and pasted that. We should return `null` if the method returns `true` not the other way around.
Mehrdad Afshari
@Marc Gravell: He had posted a code snippet. This requirement can be inferred from it.
Mehrdad Afshari
Well, maybe... but if we knew the code was perfectly implementing his intentions, it probably wouldn't be here?
Marc Gravell
@Marc: lol. Indeed. But we can sometimes assume it's *partially describing* intentions.
Mehrdad Afshari
@Mehrdad - This worked! I had my logic inverted for the ?: conditional operation. Thanks for the help! @Marc Gravell: yeah, I can see how my requirements were stated clearly, thank you for your assistance as well.
Andy May
That was supposed to say *NOT* clearly stated.
Andy May
A: 

Try:

var accountSettings = from settings in templateXML.Descendants("Account")
      where settings.Element("AccountExpriationDate") != null
      && !String.IsNullOrEmpty(settings.Element("AccountExpriationDate").Value)
      select new Account 
                  {
       AccountExpirationDate = DateTime.Parse(settings.Element("AccountExpirationDate").Value)
      };
Alexander Kahoun
A: 

You can just use:

from settings in templateXML.Descendants("Account")
let el = settings.Element("AccountExpirationDate")
let el2 = (el == null || string.IsNullOrEmpty(el.Value)) ? null : el
select new Account {
    AccountExpirationDate = (DateTime?)el2
};

there is a conversion operator that works this magic using standard xml datetime formatting, and which returns null if the element doesn't exist (note I don't read .Value).

Marc Gravell
This will throw an exception if the element exists but is empty.
Mehrdad Afshari
(fixed, but that wasn't a requirement in the original question)
Marc Gravell