Search code examples
c#linq-to-xmlxelement

Remove element from XML based on attribute value?


I was trying to remove a descendant element from an XElement (using .Remove()) and I seem to get a null object reference, and I'm not sure why.

Having looked at the previous question with this title (see here), I found a way to remove it, but I still don't see why the way I tried 1st didn't work.

Can someone enlighten me ?

  String xml = "<things>"
             + "<type t='a'>"
             + "<thing id='100'/>"
             + "<thing id='200'/>"
             + "<thing id='300'/>"
             + "</type>"
             + "</things>";

  XElement bob = XElement.Parse(xml);

  // this doesn't work...
  var qry = from element in bob.Descendants()
            where element.Attribute("id").Value == "200"
            select element;
  if (qry.Count() > 0)
     qry.First().Remove();

  // ...but this does
  bob.XPathSelectElement("//thing[@id = '200']").Remove();

Thanks, Ross


Solution

  • The problem is that the collection you are iterating contains some element that don't have the id attribute. For them, element.Attribute("id") is null, and so trying to access the Value property throws a NullReferenceException.

    One way to solve this is to use a cast instead of Value:

    var qry = from element in bob.Descendants()
              where (string)element.Attribute("id") == "200"
              select element;
    

    If an element doesn't have the id attribute, the cast will returns null, which works fine here.

    And if you're doing a cast, you can just as well cast to an int?, if you want.