C# populating class array from xml linq results in FormatException

I'm getting a FormatException error "Input string was not in a correct format." error...

Employee class is all strings except the Status(int), Type(int) and Displayed(bool)

public partial class Version2 : System.Web.UI.Page {

        private Employee[] Employees;

        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                XDocument xdoc = XDocument.Load(Server.MapPath("~/")+ "V2Employees.xml");
                IEnumerable<XElement> emps = xdoc.Root.Descendants();

                Employees = emps.Select(x => new Employee()
                {
                    Employee_ID = x.Attribute("id").Value,
                    First_Name = x.Element("First_Name").Value,
                    Last_Name = x.Element("Last_Name").Value,
                    Classification_Group = x.Element("Classification_Group").Value,
                    Classification_Level = x.Element("Classification_Level").Value,
                    Postion_Number = x.Element("Postion_Number").Value,
                    English_Title = x.Element("English_Title").Value,
                    French_Title = x.Element("French_Title").Value,
                    Location = x.Element("Location").Value,
                    Language = x.Element("Language").Value,
                    Department_ID = x.Element("Department_ID").Value,
                    Status = int.Parse(x.Element("Status").ToString()),
                    Type = int.Parse(x.Element("Type").ToString()),
                    Displayed = false}).ToArray();
        }

Example XML going in:

    <?xml version="1.0" encoding="utf-8" ?>
    <employees>
      <employee id="1">
        <First_Name>Jane</First_Name>
        <Last_Name>Doe</Last_Name>
        <Classification_Group>AA</Classification_Group>
        <Classification_Level>02</Classification_Level>
        <Postion_Number>12345</Postion_Number>
        <English_Title>Bob</English_Title>
        <French_Title></French_Title>
        <Location>Null Island</Location>
        <Language>English</Language>
        <Department_ID>000001</Department_ID>
        <Status>1</Status>
        <Type>4</Type>
      </employee>
</employees>
Jon Skeet
people
quotationmark

By calling ToString on an XElement, you're ending up with the whole element as a string, e.g.

<Status>4</Status>

... and trying to parse that as an int. I would strongly suggest:

  • Just using the Value property or a cast to string when you want the value of an element as a string (no need for a ToString call afterwards)
  • Using a cast to int when you want to convert an XElement's value to an integer

I would write your Select as:

// Property names adjusted to .NET naming conventions, type of
// PositionNumber changed to an int.
Employees = emps.Select(x => new Employee
{
    EmployeeId = (string) x.Attribute("id"),
    FirstName = (string) x.Element("First_Name"),
    LastName = (string) x.Element("Last_Name"),
    ClassificationGroup = (string) x.Element("Classification_Group"),
    ClassificationLevel = (string) x.Element("Classification_Level"),
    PositionNumber = (int) x.Element("Postion_Number"),
    EnglishTitle = (string) x.Element("English_Title"),
    FrenchTitle = (string) x.Element("French_Title"),
    Location = (string) x.Element("Location"),
    Language = (string) x.Element("Language"),
    DepartmentId = (string) x.Element("Department_ID"),
    Status = (int) x.Element("Status"),
    Type = (int) x.Element("Type"),
    Displayed = false
}

You might want to use .Value instead of the cast to string, which will mean you get a NullReferenceException if the element is missing the appropriate sub-element. You may want to use the above form instead, then have a Validate method to check that it has all the required information - that would probably allow you to report errors more clearly:

  • You could say which property is missing rather than just getting an exception
  • You could report multiple missing properties in a single error message

people

See more on this question at Stackoverflow