Gerry
Gerry

Reputation: 149

Delete all children from XML node retaining the </tag> tag

I am making a “simple” program to update an xml file.

XML snippet

<statistics>
    <offices location=”city1” >
        <office name=”office1”/>
        <office name=”office2”/>
    </offices>
    <offices location=”city2” >
        <office name=”office3”/>
        <office name=”office4”/>
    </offices>
</statistics>

My sequence of events is:

  1. Load the xml into a treeview

  2. Delete some children, add some, move some between parents in the treeview.

  3. Delete all the children in the xml.

  4. Traverse the treeview and add the children back in the xml.

  5. Save the file.

The problem is that when I delete all the children the </offices> tag is removed in order to preserve integrity and I am left with

<offices location=”city1” />
<offices location=”city2” />

If I now insert the new offices I get

<offices location=”city1” />
<office name=”office1”/>
<office name=”office2”/>
<offices location=”city2” />
<office name=”office3”/>
<office name=”office4”/>

Is there a way to delete the children and keep the </offices> tag or am I going about this all wrong? Thanks for any help, Gerry.

This is how I delete the children

private void deleteAllOffices(XDocument doc)
{
   var offices = doc.Root.Descendants("offices").ToList();
   foreach (var factor in offices)
   {
        var location = factor.Attribute("location").Value;
        // Delete the children
        deleteChildren(doc, location);
    }
}
private void deleteChildren(XDocument doc, string catg)
{
    var lv1s = from lv1 in doc.Descendants("offices")
               where lv1.Attribute("location").Value.Equals(catg)
               select new
               {
                   Children = lv1.Descendants("office")
               };

    //Loop through results
    foreach (var lv1 in lv1s)
    {
       foreach (var lv2 in lv1.Children.ToArray())
         lv2.Remove();
    }
}

This is how I add the offices back to the xml

// First delete all the offices
deleteAllOffices(doc);
// Now add the offices from the treeview
//Create a TreeNode to hold the Parent Node

TreeNode temp = new TreeNode();
//Loop through the Parent Nodes
for (int k = 0; k < treeView1.Nodes.Count; k++)
{
   //Store the Parent Node in temp
   temp = treeView1.Nodes[k];

   //Now Loop through each of the child nodes in this parent node i.e.temp
   for (int i = 0; i < temp.Nodes.Count; i++)
       {
          doc.Element("statistics")
             .Elements("offices")
             .Where(item => item.Attribute("location").Value == temp.Text).FirstOrDefault()
             .AddAfterSelf(new XElement("office", new XAttribute("name", temp.Nodes[i].Text)));
       }
 }
 doc.Save(@"d:\temp\stats.xml");

Upvotes: 0

Views: 131

Answers (1)

Hans Kesting
Hans Kesting

Reputation: 39339

The problem is in that AddAfterSelf method: that adds the new XElement after the current node, as sibling where you need child.

You need the Add method of XElement (or rather XContainer) to add that new XElement as a child element.

By the way, for XML <offices location="city1" /> is identical to <offices location="city1"></offices>

Upvotes: 1

Related Questions