1

I try to read data from a Xml file. My plan is to save all students as an object of Student with the name and the semester.

<persons>
    <student><name>255211</name><semester>MI</semester></student>
    <student><name>255212</name><semester>MI</semester></student>
    <student><name>255213</name><semester>MI</semester></student>
</persons>

I found a guide with XmlReader and switch case so i tried it.

private static void readData()
        {
            XmlTextReader reader = new XmlTextReader("data.xml");

            while (reader.Read())
            {
                if (reader.NodeType == XmlNodeType.Element)
                {
                    switch (reader.Name)
                    {
                        case "student":
                            Student student = new Student();
                            Students.Add(student);
                            break;
                        case "name":
                            student.name = reader.ReadString();
                            //Console.WriteLine(student.name);
                            break;
                        case "semester":
                            student.semester = reader.ReadString();
                            break;
                    }
                }
            }
            reader.Close();
        } 

My problem now is that Visual Studio Code gives me an error: error CS0165: Use of unassigned local variable 'student' (student.name in case "name"). I guess it is because there wouldn't be a student.name if the code does not go into case "student". I tried with try catch but that didn't helped me.

How can I achieve that every student gets his name and semester correct?

DennisG
  • 25
  • 1
  • 5
  • possible duplicate : https://stackoverflow.com/questions/9233000/why-compile-error-use-of-unassigned-local-variable – nalka Feb 05 '19 at 11:58

1 Answers1

3

You only assign student in the "student" case; from the compiler's point of view, student is unassigned at the start of the "name" and "semester" cases, so you can't set properties on them. You might have knowledge that <student> always comes first, but the compiler doesn't know that. Also, from it's view, the scope is separate for each element. But if you're 100% sure that there's always a <student> between each then you could probably move the assignment around a little:

Student student = null;
while (reader.Read())
{
    if (reader.NodeType == XmlNodeType.Element)
    {
        switch (reader.Name)
        {
            case "student":
                student = new Student();
                Students.Add(student);
                break;
            case "name":
                student.name = reader.ReadString();
                //Console.WriteLine(student.name);
                break;
            case "semester":
                student.semester = reader.ReadString();
                break;
        }
    }
}

However, in reality, in most scenarios, I would strongly recommend using XmlSerializer or similar to parse the input into objects, and then just deal with them as objects.

Based on the xml layout in the question, this should work:

public class Student {
    [XmlElement("name")]
    public string Name {get;set;}
    [XmlElement("semester")]
    public string Semester {get;set;}
}
[XmlRoot("persons")]
public class SomeData {
    [XmlElement("student")]
    public List<Student> Students {get;} = new List<Student>();
}

and:

var ser = new XmlSerializer(typeof(SomeData));
var data = (SomeData)ser.Deserialize(source);
List<Student> students = data.Students;
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • I've deleted my similar answer. Thinking about it, I prefer this version that throws a `NullReferenceException` if the assumption is violated rather than continuing on regardless but it still only saves you from an initial leading `name` or `semester` element. – Damien_The_Unbeliever Feb 05 '19 at 12:00
  • @Damien_The_Unbeliever my preference is actually for the bit I've just edited in :) – Marc Gravell Feb 05 '19 at 12:01