Search code examples
c#.netxmllinq

Delete all node from XML with LINQ where value is specific


I have a XMl file with the following structure:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<FlashMemory>
    <FlashItems>
        <FlashItem>
            <Keyword KID="1234">XY</Keyword>
            <Header Version="1">XY</Header>
            <Gap DivisibleBy="8">XY</Gap>
            <Datatype DID="12345">XY</Datatype>
            <Length>2</Length>
            <ProductionSteps>
                <ProductionStep>
                    <Step>XY</Step>
                    <Source>XY</Source>
                    <Value>XY/Value>
                    <DocTarget>
                        <Target>None</Target>
                    </DocTarget>
                </ProductionStep>
            </ProductionSteps>
        </FlashItem>
        <FlashItem>
        .
        .
        .
        </FlashItem>
    </FlashItems>
</FlashMemory>

I want to remove all <FlashItem></FlashItem> node where the <Step> value is equal with some value. I tried with LINQ, but the result of the query is always null.

XDocument xmlDoc = XDocument.Load("test.xml");

xmlDoc.Descendants("FlashItems")
      .Elements("FlashItem")
      .Elements("ProductionSteps")
      .Elements("ProductionStep")
      .Elements("Step")
      .Where(x => x.Value == "testvalue").Remove();

Any suggestion for this in C#?

Update:

var nodes = xmlDoc.Descendants("FlashItem");

var x = (from element in nodes 
         where element.Element("ProductionSteps")
                      .Element("ProductionStep")
                      .Element("Step").Value == "HecuProduction" 
         select element);

foreach (var query in x)
{
   query.Element("Flashitem").Remove();              
}

In this case the selection is working and all node what I need to delete is in the x, but when I try to delete I get a null reference exception.


Solution

  • You code does actually work ... however you do not remove the parent nodes you are going for - you are removing the step node itself.

    Give this a try:

    using System.Xml.Linq;
    
    XDocument xmlDoc = XDocument.Load("./test.xml");
    
    var nodesToRemove = xmlDoc.Descendants("FlashItems")
          .Elements("FlashItem")
          .Elements("ProductionSteps")
          .Elements("ProductionStep")
          .Elements("Step")
          .Where(x => x.Value == "testvalue");
    
    foreach (var node in nodesToRemove) {
        node.Parent.Parent.Parent.Remove();
    }