5

I'm trying to remove multiple nodes that a particular element(path) contains a value but I'm receiving a System.NullReferenceException any help where I'm going wrong would I'be much appreciated.

My xml looks like this:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<ApplicationData Version="12.5.1" RootPath="FireFox-FILES">
  <RegistrySystem>
    <DIR Operation="+" Path="C:\Temp\Microsoft\MediaPlayer\ShimInclusionList" />
    <DIR Operation="+" Path="C:\Temp\MediaPlayer\ShimInclusionList\MM.EXE" />
    <DIR Operation="+" Path="C:\Temp\MediaPlayer\ShimInclusionList\plugin-container.exe" />
    <DIR Operation="+" Path="C:\Temp\Microsoft\MediaPlayer">
      <ENTRY Name="" Value="43.0.4" Type="1" />
      <ENTRY Name="CurrentVersion" Value="43.0.4 (x86 en-GB)" Type="1" />
    </DIR>
    <DIR Operation="+" Path="C:\Program Files\Microsoft\MediaPlayer\ShimInclusionList\plugin-container.exe" />
    <DIR Operation="+" Path="C:\Program Files\Microsoft\MediaPlayer\ShimInclusionList2\plugin.exe" />
    <DIR Operation="+" Path="C:\Program Files\Microsoft\MediaPlayer\ShimInclusionList2\container.exe" />
    <DIR Operation="+" Path="C:\Program Files\Microsoft\MediaPlayer\ShimInclusionList4">
      <ENTRY Name="" Value="43.0.4" Type="1" />
      <ENTRY Name="CurrentVersion" Value="43.0.4 (x86 en-GB)" Type="1" />
    </DIR>
  </RegistrySystem>
</ApplicationData>

My code looks like this:

XDocument xdoc = XDocument.Load(XmlFile);
foreach (var node in xdoc.Descendants("DIR").Where(status => status.Attribute("Path").Value.Contains(@"C:\Temp\")))
{
    node.Remove();

}
xdoc.Save(XmlFile);

I'm not sure where I'm going wrong.

psfinaki
  • 1,173
  • 10
  • 22
BillyDay
  • 147
  • 2
  • 10
  • 5
    [What is a `NullReferenceException` and how do I fix it?](http://stackoverflow.com/q/4660142/447156) – Soner Gönül Mar 02 '16 at 09:13
  • Is it possible that `xdoc` is null after the attempt to load it from the XML file? – Codor Mar 02 '16 at 09:16
  • Sorry I mean where Attribute. – BillyDay Mar 02 '16 at 09:16
  • 2
    Are you sure you don't have any `DIR` elements without a `Path` attribute? That would certainly cause the problem... Also note that you can just call `Remove()` on a query returning a sequence of elements, and it will remove then all :) – Jon Skeet Mar 02 '16 at 09:17
  • 2
    This *isn't* really a duplicate of the canonical question. The exception is thrown within framework code in a very non-obvious way. The normal kind of diagnostics don't help. – Jon Skeet Mar 02 '16 at 09:22
  • OK, I recreatd this. When first node is Remove and I want to get next value in foreach loop code is throw NullReferenceException. First node can by Removed – blogprogramisty.net Mar 02 '16 at 09:32

1 Answers1

8

I'm not sure why you're getting the exception, but I strongly suspect it's because you're modifying the document while you're querying it.

If you change your code to use a ToList() call to get the list of nodes to remove, that doesn't throw:

foreach (var node in xdoc.Descendants("DIR")
           .Where(status => status.Attribute("Path").Value.Contains(@"C:\Temp\"))
           .ToList())
{                                                                            
    node.Remove();
}

However, that's not the best way. The best approach is to use the Remove(this IEnumerable<XElement>) extension method:

xdoc.Descendants("DIR")
    .Where(status => status.Attribute("Path").Value.Contains(@"C:\Temp\"))
    .Remove();

No need for a foreach loop at all. Now to make it robust in the face of DIR elements without a Path attribute, you can cast to string instead:

xdoc.Descendants("DIR")
    .Where(status => ((string) status.Attribute("Path") ?? "").Contains(@"C:\Temp\"))
    .Remove();
Grundy
  • 13,060
  • 3
  • 33
  • 51
Jon Skeet
  • 1,261,211
  • 792
  • 8,724
  • 8,929
  • Thanks Jon, adding the .Remove() on the end of the query and removing it out the for loop fixed it i suspect your right that i was trying to modify the document while querying it. added the ?? to handle null vales aswell. Thanks for your help... – BillyDay Mar 02 '16 at 09:34