I have an XML file that looks like this
<modules>
<level4>
<module>
<name>Programming Principles I</name>
<credit>20</credit>
<assessments>
<assessment>
<assessment_name>Course Work 1</assessment_name>
<weight>50</weight>
<passing>55</passing>
<obtain>55</obtain>
</assessment>
<assessment>
<assessment_name>Course Work 2</assessment_name>
<weight>50</weight>
<passing>55</passing>
<obtain>55</obtain>
</assessment>
</assessments>
</module>
</level4>
</modules>
Whilst, getting into assessment
childs of parent assessments
it returns null..
using this code
XDocument xml = XDocument.Load("module.xml");
var result = xml.Descendants("module")
.FirstOrDefault(x => (string)x.Element("name") == "Programming Principles I");
var assessments = result.Element("assessments");
var assessment = assessments.Descendants("assessment");
foreach(var a in assessment)
{
a.Remove();
}
At this assessment
variable I am getting null value exception. The LINQ query works fine but the next two lines I am uncertain. I am actually, removing all the nodes present inside assessments
node.
Modifying a lazily-evaluated query while iterating over it is basically dangerous.
Two options:
Use the Remove
extension method. Less code, and it'll work! Replace your whole loop with:
assessment.Remove();
Evaluate the query before you start removing anything, storing the result as a list. At this point, it's fine to use foreach
because removing the element from its parent won't remove it from the list:
foreach(var a in assessment.ToList())
{
a.Remove();
}
You still have a problem in your code though - you're using FirstOrDefault()
when finding the module element, which means you're anticipating that you might not find it - but you're ignoring that possibility in the next line.
I'd probably rewrite the code to this:
var assessmentsToRemove = xml
.Descendants("module")
.Where(mod => (string) mod.Element("name") == "Programming Principles I")
.Elements("assessments")
.Elements("assessment");
assessmentsToRemove.Remove();
You could do it all in a single statement if you want, but the above approach makes it easier to diagnose issues later in the debugger.
See more on this question at Stackoverflow