Search code examples
c#xmllinq-to-xmlspanning-tree

Minimum subtree on xml with XDocument


I have xml document that needs to be proceeded using XDocument

<elem c="98500000">
    <elem c="98510000">
      <elem c="98511000"/>
      <elem c="98512000"/>
      <elem c="98513000">
        <elem c="98513100"/>
        <elem c="98513200"/>
        <elem c="98513300"/>
        <elem c="98513310"/>
      </elem>
      <elem c="98514000"/>
    </elem>
  </elem>

I try to get minimum subtree by selected node attributes e.g. 98512000, 98513300, 98514000 :

<elem c="98500000">
    <elem c="98510000">
      <elem c="98512000"/>
      <elem c="98513000">
        <elem c="98513300"/>
      </elem>
      <elem c="98514000"/>
    </elem>
  </elem>

Solution

  • Given a list of desired c values, you can remove elements where c attribute value is not in the list and no descendant elements has c attribute value in the list :

    var doc = XDocument.Parse("your XML document string here");
    var list = new List<string>(){"98512000", "98513300", "98514000"};
    doc.Descendants()
        // all `c` value doesn't match current element's `c` attribute value
       .Where(o => list.All(c => (string)o.Attribute("c") != c) 
                        && 
        // and all descendant elements doesn't have matching `c` attribute value
                   o.Descendants().All(d => !list.Any(c => (string)d.Attribute("c") == c)))
       .Remove();
    Console.WriteLine(doc.ToString());
    

    dotnetfiddle demo

    output :

    <elem c="98500000">
      <elem c="98510000">
        <elem c="98512000" />
        <elem c="98513000">
          <elem c="98513300" />
        </elem>
        <elem c="98514000" />
      </elem>
    </elem>