how to remove all the childnodes of the specified xmlnode in C# 4.0?

16,289

Solution 1

Use LINQ to XML to remove all descendants of the Paragraph elements:

XElement root = XElement.Load(@"H:\Sample-8-final_1.xml");
root.Descendants("Paragraph").Descendants().Remove();

Note: you need to put using System.Xml.Linq; at the top of your file.

Solution 2

The problem is that you are changing the thing you are iterating over in these lines:

foreach (XmlNode yyNode in xxNode.ChildNodes)
{
    yyNode.ParentNode.RemoveChild(yyNode);
}

This is easier to spot if you were to replace yyNode.ParentNode with xxNode (this is guaranteed to be that). This is causing the iterator to get confused and skip some things you don't want it to.

Probably easier though is just to call xxNode.RemoveAll(). See docs: http://msdn.microsoft.com/en-us/library/system.xml.xmlnode.removeall

However note that as Mahen says this will remove your attributes as well so is often not the desired solution (and not in this case for example).

Solution 3

Chris explained that the iteration fails because you're modifying ChildNodes (by deleting them) as you're iterating through that collection. He suggested using RemoveAll() instead. But RemoveAll() deletes attributes as well as child elements, which is not what I want. So this is what I wrote to iterate safely while preserving attributes (in VB.NET):

Private Shared Sub RemoveAllChildren(element As XmlElement)
    ' you can't iterate and delete in the same loop, because you would be modifying .ChildNodes
    Dim childrenList = New ArrayList()
    For Each child In element.ChildNodes
        childrenList.Add(child)
    Next
    For Each child In childrenList
        child.ParentNode.RemoveChild(child)
    Next
End Sub

Solution 4

there is no problem with the code you just have to be exact with your literals. they are case-sensitive. write "page" instead of "PAGE" and "Paragraph" instead of "PARAGRAPH" then the code works just fine.

Share:
16,289
Saravanan
Author by

Saravanan

I am Saravanan MCA Graduate.I am working as a Senior Developer in java environment. Email:[email protected]

Updated on June 27, 2022

Comments

  • Saravanan
    Saravanan almost 2 years

    This is my xml.

    <Document>
    <page no="1">
      <Paragraph no="1">
        <Line>line1</Line>
      </Paragraph>
      <Paragraph no="2">
        <Line>line2</Line>
      </Paragraph>
    </page>
    <page no="2">
      <Paragraph no="1">
        <Line>line1</Line>
      </Paragraph>
      <Paragraph no="2">
        <Line>line2</Line>
      </Paragraph>
    </page>
    </Document>
    

    My C# code is

    XmlDocument xd = new XmlDocument();
                xd.Load(@"H:\Sample-8-final.xml");
                XmlNodeList pnodelist = xd.GetElementsByTagName("page");
                XmlNodeList xdChildNodeList = xd.ChildNodes;
    
                for (int i = 0; i < pnodelist.Count; i++)
                {
                    XmlNode pageNode = pnodelist[i];
                    foreach (XmlNode xxNode in pageNode.ChildNodes)
                    {
                        if (xxNode.Name.ToString().Trim().Equals("Paragraph"))
                        {
                            foreach (XmlNode yyNode in xxNode.ChildNodes)
                            {
                                yyNode.ParentNode.RemoveChild(yyNode);
                            }
                        }
                    }
                    xd.Save(@"H:\Sample-8-final_1.xml");
    

    my Required output is

    <Document>
    <page no="1">
      <Paragraph no="1">
      </Paragraph>
      <Paragraph no="2">
      </Paragraph>
    </page>
    <page no="2">
      <Paragraph no="1">
      </Paragraph>
      <Paragraph no="2">
      </Paragraph>
    </page>
    </Document>
    

    but my code produced wrong result like below:

    <Document>
        <page no="1">
          <Paragraph no="1">
          </Paragraph>
          <Paragraph no="2">
            <Line>line2</Line>
          </Paragraph>
        </page>
        <page no="2">
          <Paragraph no="1">
          </Paragraph>
          <Paragraph no="2">
            <Line>line2</Line>
          </Paragraph>
        </page>
        </Document>
    

    Please Guide me to get out of this issue...

  • Mahen
    Mahen about 9 years
    xxNode.RemoveAll will remove the attributes as well, and in this example it will remove the "no" attribute, which he wants to keep.
  • Chris
    Chris about 9 years
    Thanks, Mahen. I'll update answer to reference this. Looking at it again I think what I wrote duplicated his code which attempted to delete all child nodes. I'm not going to spend the time now to work out whether his original code would have stripped all attributes too though. :)
  • kooch
    kooch almost 5 years
    Yes, the issue is definitely that the collection is being modified. What i will often find myself doing when i'm in this situation is just iterate through the collection backwards. This prevents any errors related to the collection being modified. for (int i = xxNode.ChildNodes.Count - 1; i >=0; i--) { xxNode.RemoveChild(xxNode.ChildNodes[i]); }