Creating lists from XML with optional elements

I am working on some XML documents and trying to parse them into Lists. I have read the following answers and articles but, I couldn't find a way to parse optional "Values" tag and it's elements for the code below.

http://blogs.msdn.com/b/ericwhite/archive/2009/05/14/working-with-optional-elements-and-attributes-in-linq-to-xml-queries.aspx , LINQ to XML optional element query , Can XML with optional elements be used with LINQ and Anonymous Types? , How to Parse Optional or Null XML Elements & Attributes with LINQ?

The code:

XDocument xdoc1 = XDocument.Load("sample.xml");
List<Message> messages = new List<Message>();
messages = (from _message in xdoc1.Element("Messages").Elements("Message")
select new Message
{
    Id = _message.Element("Id").Value,
    Alias = _message.Element("Alias").Value,
    Fields = (from _field in _message.Element("Fields").Elements("Field")
        select new Field
        {
            FieldName = _field.Element("FieldName").Value,
            StartIndex = Convert.ToInt16(_field.Element("StartIndex").Value),
            StopIndex = Convert.ToInt16(_field.Element("StopIndex").Value),
            DefaultBits = _field.Element("DefaultBits").Value,
            CalculationMethod = (CalculationMethods.Types)Enum.Parse(typeof(CalculationMethods.Types), _field.Element("CalculationMethod").Value),
            Values = (from _value in _field.Element("Values").Elements("Value")
                select new Value
                {
                    Bits = _value.Element("Bits").Value,
                    Meaning = _value.Element("Meaning").Value
                }).ToList()
        }).ToList()
}).ToList();

Some "Fields" has "Field"s with "FieldName", "StartIndex", "StopIndex", "DefaultBits", "CalculationMethod" and optionally "Values". How can I fix the code for optional "Values" tags in XML?

Jon Skeet
people
quotationmark

Instead of using .Value, use the explicit conversions in XElement. So for example:

FieldName = (string) _field.Element("FieldName"),
StartIndex = (short?) _field.Element("StartIndex")

You'll end up with null values for absent elements, because that's what the custom conversions on XElement do when the operand is null (and the return type is a reference type or a nullable value type).

For Values, it's even easier - you just need to change _field.Element("Values") to _field.Elements("Values"):

Values = (from _value in _field.Elements("Values").Elements("Value")
          select new Value
          {
              Bits = _value.Element("Bits").Value,
              Meaning = _value.Element("Meaning").Value
          }).ToList()

That way, _field.Elements("Values") will return an empty sequence if there's no Values element.

people

See more on this question at Stackoverflow