Saravanan
Saravanan

Reputation: 11612

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

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...

Upvotes: 3

Views: 20606

Answers (6)

EminST
EminST

Reputation: 79

Easy, just use while:

while (node.HasChildNodes)
{
    node.RemoveChild(node.FirstChild);
}

Upvotes: 0

Paul B
Paul B

Reputation: 11

while (parentNode.ChildNodes.Count > 0) 
{
   parentNode.RemoveChild(parentNode.ChildNodes[0]);
}

Should also work.

Upvotes: 1

Chris
Chris

Reputation: 27627

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).

Upvotes: 3

Rory O&#39;Kane
Rory O&#39;Kane

Reputation: 30428

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

Upvotes: 3

Adam
Adam

Reputation: 15803

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.

Upvotes: 11

Stephan Schinkel
Stephan Schinkel

Reputation: 5540

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.

Upvotes: 2

Related Questions