Search code examples
c#linqxelement

Accessing XElement's attribute with Linq


I'm parsing an XElement object like this one

XElement teachers = new XElement("Teachers",
    new XElement("Teacher1", 
        new XAttribute("Age", 27)),
    new XElement("Teacher2",
        new XAttribute("Age", 60)),
    new XElement("Teacher3"),
        new XAttribute("Age", 50));

With this code:

IEnumerable<string> oldTeachers = from teacher in teachers.Elements()
                                        where int.Parse(teacher.Attribute("Age").Value) > 40
                                        orderby teacher.Name.ToString() ascending 
                                        select teacher.Name.ToString();

But i get a runtime error saying "Object reference not set to an instance of an object on the where line. What am I doing wrong?

EDIT:

I found the problem being the XElement declaration: the right one should have been this:

XElement teachers = new XElement("Teachers",
    new XElement("Teacher1", 
        new XAttribute("Age", 27)),
    new XElement("Teacher2",
        new XAttribute("Age", 60)),
    new XElement("Teacher3",
        new XAttribute("Age", 50)));

Solution

  • First of all, you should not establish identity through the name of an element. The name of an element should be the name of a concept of what it represents. By naming your elements Teacher1, Teacher2, and Teacher3, you're making it harder to process than it should. If you need identity, add an attribute to your teachers.

    var teachers = new XElement("Teachers",
        new XElement("Teacher",
            new XAttribute("Id", 1),
            new XAttribute("Age", 27)
        ),
        new XElement("Teacher",
            new XAttribute("Id", 2),
            new XAttribute("Age", 60)
        ),
        new XElement("Teacher",
            new XAttribute("Id", 3),
            new XAttribute("Age", 50)
        )
    );
    

    In LINQ to XML, if you needed the value of an Attribute/Element, you should cast to the appropriate type.

    var oldTeachers =
        from teacher in teachers.Elements("Teacher")
        where (int)teacher.Attribute("Age") > 40
        orderby (int)teacher.Attribute("Id") ascending
        select "Teacher" + (int)teacher.Attribute("Id"); // or simply return the Id