Reputation: 11612
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
Reputation: 79
Easy, just use while:
while (node.HasChildNodes)
{
node.RemoveChild(node.FirstChild);
}
Upvotes: 0
Reputation: 11
while (parentNode.ChildNodes.Count > 0)
{
parentNode.RemoveChild(parentNode.ChildNodes[0]);
}
Should also work.
Upvotes: 1
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
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
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
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