Sean Glover
Sean Glover

Reputation: 520

Search all child nodes of XML node for a value and remove the grandparent node

Trying to use

exportDoc.Root.Elements("string").Where(node => !(node.Element("product").HasElements) || node.Element("product").Element("type").Value != product).Remove();

to remove the nodes in my XML document where the product string I'm searching for doesn't occur. Here is a sample of my XML structure:

<root>
   <string id = "Hithere">
      <product>
         <type>orange</type>
         <type>yellow</type>
         <type>green</type>
      <product>
      <element2/>
      <element3/>
    </string>
    <string id ="...">
     ...
     ... 
</root>

So I need to look under the product element of each string element AND at each of the type elements therein to see if the value of string product (input to the method where this is contained) occurs. At present, it looks like my code only removes the node if the product string I'm searching for matches the value of just the first type element.

The whole point is to remove all string nodes from this xdoc that don't have the product I'm looking for listed under their product element.

Upvotes: 1

Views: 2269

Answers (2)

k.m
k.m

Reputation: 31474

You need to change your search condition slightly:

var nodesToRemove = xDoc.Root
    .Elements("string")
    .Where(node =>
        !(node.Element("product").HasElements) ||
        node.Element("product").Elements("type").All(x => x.Value != product))
    .ToList();

This should match elements which all string:product:types differ from product value (or in other words - if at least one <type> will match your product, it won't be marked for removal).

Upvotes: 1

Henk Holterman
Henk Holterman

Reputation: 273681

You can't Remove() while you're still enumerating (deferred execution).

You need something more like:

// untested
var toRemove = exportDoc.Root.Elements("string")
    .Where(node => !(node.Element("product").HasElements) ||
           node.Element("product").Element("type").Value != product).ToList();
toRemove.Remove();

Upvotes: 1

Related Questions