Remove Child Nodes reverses order of Xpath

Topics: Developer Forum
Jan 3, 2010 at 2:20 AM

Hello

I was following the information in this thread: http://htmlagilitypack.codeplex.com/Thread/View.aspx?ThreadId=24346 for when I wanted to remove all of the <font> tags from an HtmlDocument. When I did this, it reversed the order of the attributes. Before I remove the child nodes, the xpath comes back as:

1
2
3
4
5
6

and so on.

When I execute this code:

HtmlNodeCollection nc = doc.DocumentNode.SelectNodes("//font");
            if (nc != null)
            {
                foreach (HtmlNode nd in nc)
                    nd.ParentNode.RemoveChild(nd, true);
            }
The order is reversed:
6
5
4
3
2
1
Has anyone experienced this? And does anyone know why/how I can get around it?
Thanks
Dec 2, 2010 at 3:54 PM

I am also seeing similar behavior with RemoveChild(n, true):

 

                var nodes = doc.DocumentNode.SelectNodes("//font|//em|//strong|//b|//i");

                if (nodes != null && nodes.Count > 0)
                {
                    foreach (var n in nodes)
                    {
                        n.ParentNode.RemoveChild(n, true);
                    }
                }

 

My node order seems to be reversed as well.  Is there a different way to get around this problem?

Jan 17, 2011 at 12:33 AM

The "prev" reference is unnecessary.  Looping backwards through the children and inserting after the parent works.  Here is the updated RemoveChild method.

        public HtmlNode RemoveChild(HtmlNode oldChild, bool keepGrandChildren)

        {

            if (oldChild == null)

            {

                throw new ArgumentNullException("oldChild");

            }

            if ((oldChild._childnodes != null) && keepGrandChildren)

            {

                // get prev sibling

                //HtmlNode prev = oldChild.PreviousSibling;

int count = oldChild._childnodes.Count;
                // reroute grand children to ourselves

for (var i = count - 1; i >= 0; i--) {

//looping through children backwards allows us to insert after the parent

  //and end up with the same node order

HtmlNode grandchild = oldChild._childnodes[i];

//InsertAfter(grandchild, prev);

InsertAfter(grandchild, oldChild);

}

            }

            RemoveChild(oldChild);

            _outerchanged = true;

            _innerchanged = true;

            return oldChild;

        }