2

Im having some trouble with a linq query into an xml tree. Here is what the tree structure looks like:

<Student>
  <ID> Hello </Hello>
  <Classroom>
     <Name> 1B </Name>
     <Year> 1 </Year>
  </Classroom>
  <Classroom>
     <Name> 2B </Name>
     <Year> 2 </Year>
  </Classroom>
  <Classroom>
     <Name> 3B </Name>
     <Year> 3 </Year>
  </Classroom>
</Student>

Now this is one student entry among 5. say i am passed an XElement Student node from another method and i want to search for a classroom given the XElement Student node and the classroom name. So i have to write a method like this:

getClassRoomNode(XElement StudentNode, string classroomName)

This is what ive tried. Please let me know where i am wrong

XElement classroom = StudentNode.Descendants("Classroom")
                                .Where(arg => arg.Element("Name").Value == classroomName)
                                .Select(arg => arg.Parent)
                                .First();

This returns the StudentNode back again instead of a classroom node. Can anyone please help me out with this?

2
  • 1
    There is an error in your XML, not well formed "<ID>" Commented Aug 10, 2011 at 15:54
  • sorry, its just an example... fixed now Commented Aug 10, 2011 at 15:55

5 Answers 5

2

You don't need to select parent, just the get the First(), or even better Single() class room.

XElement classroom = StudentNode.Descendants("Classroom")
    .Single(arg => arg.Element("Name").Value == classroomName);

I suggest it is better to error rather than ignore subsequent matches. If the intention is to match the first of many matches then obviously,

XElement classroom = StudentNode.Descendants("Classroom")
    .First(arg => arg.Element("Name").Value == classroomName);
Sign up to request clarification or add additional context in comments.

Comments

1

Get rid of the Select, you are reselecting the parent!

XElement classroom = StudentNode.Descendants("Classroom").Where(arg => arg.Element("Name").Value == classroomName).First();

1 Comment

First() could replace Where()
1

Your code does exactly what it's told to: select the <classrom> node where the content of the name element equals classroomName, and then select the parent of that <classrom> node, i.e. the <student> node.

Fix:

XElement classroom =
    StudentNode.Elements("Classroom")
               .First(arg => (string)arg.Element("Name") == classroomName);

This returns the first <classrom> node where the content of the name element equals classroomName.

3 Comments

Wouldn't it complain because classroomName is not an XElement
@Jodrell: No, because (string)arg.Element("Name") returns the content of the <name> element as string.
you are right, I missed the explicit cast msdn.microsoft.com/en-us/library/bb155263.aspx note the CLS compliance.
0

You are selecting the parent node of the Classroom node. Change the query like so:

XElement classroom = StudentNode.Descendants("Classroom").First(arg => arg.Element("Name").Value == classroomName);

Instead of using First you should use FirstOrDefault and check for a null value to stop any exceptions which may occur if no Classroom nodes are found based on your query. (Ignore this if you are handling this exception elsewhere in your code)

Enumerable.FirstOrDefault

2 Comments

.Select(arg => arg) is still redundant, why including it at all?
Additionaly, First() could replace Where()
0

This is because you are selecting the parent of the classroom nodes. Just get rid of the last selector:

XElement classroom = StudentNode.Descendants("Classroom").Where(arg => arg.Element("Name").Value == classroomName).First();

Or even simpler, as was pointed out combine First and Where together.

XElement classroom = StudentNode.Descendants("Classroom").First(arg => arg.Element("Name").Value == classroomName)

This will however throw an exception if there is no match, FirstOrDefault on the otherhand would return null on no match;

XElement classroom = StudentNode.Descendants("Classroom").FirstOrDefault(arg => arg.Element("Name").Value == classroomName)

1 Comment

First() could replace Where()

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.