See the question and my original answer on StackOverflow

The Html Agility Pack constructs a Read/Write DOM, so you can rebuild it the way you want. Here is a sample code that seems to work:

        HtmlDocument doc = new HtmlDocument();
        doc.Load("MyTest.htm");

        // get the first TR
        CloneAsParentNode(doc.DocumentNode.SelectNodes("table/tr[1]"), "thead");

        // get all remaining TRs but the last
        CloneAsParentNode(doc.DocumentNode.SelectNodes("table/tr[position()<last()]"), "tbody");

        // get the first TR (it's also the last, since it's the only one at that level)
        CloneAsParentNode(doc.DocumentNode.SelectNodes("table/tr[1]"), "tfoot");


    static HtmlNode CloneAsParentNode(HtmlNodeCollection nodes, string name)
    {
        HtmlNode parent = nodes[0].ParentNode;

        // create a new parent with the given name
        HtmlNode newParent = nodes[0].OwnerDocument.CreateElement(name);

        // insert before the first node in the selection
        parent.InsertBefore(newParent, nodes[0]);

        // clone all sub nodes
        foreach (HtmlNode node in nodes)
        {
            HtmlNode clone = node.CloneNode(true);
            newParent.AppendChild(clone);
        }

        // remove all sub nodes
        foreach (HtmlNode node in nodes)
        {
            parent.RemoveChild(node);
        }
        return newParent;
    }