// merge multiple <head> or <body> contents into one, delete the remainder, and ensure they are owned by <html> private void NormaliseStructure(string tag, Element htmlEl) { var elements = this.GetElementsByTag(tag); var master = elements.First; // will always be available as created above if not existent if (elements.Count > 1) { // dupes, move contents to master var toMove = new List <Node>(); for (var i = 1; i < elements.Count; i++) { var dupe = elements[i]; foreach (var node in dupe.ChildNodes) { toMove.Add(node); } dupe.Remove(); } foreach (var dupe in toMove) { master.AppendChild(dupe); } } // ensure parented by <html> if (!master.Parent.Equals(htmlEl)) { htmlEl.AppendChild(master); // includes remove() } }
/// <summary> /// Wrap the supplied HTML around this node. /// </summary> /// <param name="html">HTML to wrap around this element, e.g. <code><div class="head"></div></code>. Can be arbitrarily deep.</param> /// <returns>this node, for chaining.</returns> public virtual Node Wrap(string html) { if (string.IsNullOrEmpty(html)) { throw new ArgumentException("html cannot be empty."); } Element context = ParentNode is Element ? (Element)ParentNode : null; IList <Node> wrapChildren = Parser.ParseFragment(html, context, BaseUri); Node wrapNode = wrapChildren.First(); if (wrapNode == null || !(wrapNode is Element)) // nothing to wrap with; noop { return(null); } Element wrap = (Element)wrapNode; Element deepest = GetDeepChild(wrap); ParentNode.ReplaceChild(this, wrap); deepest.AddChildren(this); // remainder (unbalanced wrap, like <div></div><p></p> -- The <p> is remainder if (wrapChildren.Count > 0) { for (int i = 0; i < wrapChildren.Count; i++) { // skip first Node remainder = wrapChildren[i]; remainder.ParentNode.RemoveChild(remainder); wrap.AppendChild(remainder); } } return(this); }