/// <summary> /// Start a depth-first traverse of the root and all of its descendants. /// </summary> /// <param name="root">the root node point to traverse.</param> public void Traverse(Node root) { Node node = root; int depth = 0; while (node != null) { visitor.Head(node, depth); if (node.ChildNodeSize > 0) { node = node.ChildNode(0); depth++; } else { while (node.NextSibling == null && depth > 0) { visitor.Tail(node, depth); node = node.Parent; depth--; } visitor.Tail(node, depth); if (node == root) { break; } node = node.NextSibling; } } }
public void Head(Node node, int depth) { if (node is Element) { Element el = (Element)node; if (eval.Matches(root, el)) { elements.Add(el); } } }
public void Tail(Node node, int depth) { }
public void Head(Node node, int depth) { if (node is TextNode) { TextNode textNode = (TextNode)node; Supremes.Nodes.Element.AppendNormalisedText(accum, textNode); } else { if (node is Element) { Element element = (Element)node; if (accum.Length > 0 && (element.IsBlock || element.TagName.Equals("br")) && !TextNode.LastCharIsWhitespace(accum)) { accum.Append(" "); } } } }
public void Tail(Node source, int depth) { if (source is Element && this._enclosing.whitelist.IsSafeTag(source.NodeName)) { this.destination = this.destination.Parent; } }
// includes remove() // fast method to get first by tag name, used for html, head, body finders private Element FindFirstElementByTagName(string tag, Node node) { if (node.NodeName.Equals(tag)) { return (Element)node; } else { foreach (Node child in node.ChildNodes) { Element found = FindFirstElementByTagName(tag, child); if (found != null) { return found; } } } return null; }
public void Head(Node node, int depth) { accum.Append("<" + node.NodeName + ">"); }
/// <summary> /// Insert the specified node into the DOM before this node (as a preceding sibling). /// </summary> /// <param name="node">to add before this element</param> /// <returns>this Element, for chaining</returns> /// <seealso cref="After(Node)">After(Node)</seealso> public override Node Before(Node node) { return (Element)base.Before(node); }
internal void SetParentNode(Node parentNode) { if (this.parentNode != null) { this.parentNode.RemoveChild(this); } this.parentNode = parentNode; }
/// <summary> /// Replace this node in the DOM with the supplied node. /// </summary> /// <param name="in">the node that will will replace the existing node.</param> public void ReplaceWith(Node @in) { Validate.NotNull(@in); Validate.NotNull(parentNode); parentNode.ReplaceChild(this, (Supremes.Nodes.Node)@in); }
/// <summary> /// Insert the specified node into the DOM after this node (i.e. as a following sibling). /// </summary> /// <param name="node">to add after this node</param> /// <returns>this node, for chaining</returns> /// <seealso cref="Before(Node)">Before(Node)</seealso> public virtual Node After(Node node) { Validate.NotNull(node); Validate.NotNull(parentNode); parentNode.AddChildren(SiblingIndex + 1, node); return this; }
public void Head(Node node, int depth) { ((Supremes.Nodes.Node)node).baseUri = baseUri; }
internal void InsertInFosterParent(Node @in) { Element fosterParent = null; Element lastTable = GetFromStack("table"); bool isLastTableParent = false; if (lastTable != null) { if (lastTable.Parent != null) { fosterParent = lastTable.Parent; isLastTableParent = true; } else { fosterParent = AboveOnStack(lastTable); } } else { // no table == frag fosterParent = stack.First.Value; } if (isLastTableParent) { Validate.NotNull(lastTable); // last table cannot be null by this point. lastTable.Before(@in); } else { fosterParent.AppendChild(@in); } }
// doesn't use insertNode, because we don't foster these; and will always have a stack. private void InsertNode(Node node) { // if the stack hasn't been set up yet, elements (doctype, comments) go into the doc if (stack.Count == 0) { doc.AppendChild(node); } else { if (IsFosterInserts()) { InsertInFosterParent(node); } else { CurrentElement().AppendChild(node); } } // connect form controls to their form element if (node is Element && ((Element)node).Tag.IsFormListed) { if (formElement != null) { formElement.AddElement((Element)node); } } }
internal static bool PreserveWhitespace(Node node) { // looks only at this element and one level up, to prevent recursion & needless stack searches if (node != null && node is Element) { Element element = (Element)node; return element.Tag.PreservesWhitespace || element.Parent != null && element.Parent.Tag.PreservesWhitespace; } return false; }
/// <summary> /// Add a node to the start of this element's children. /// </summary> /// <param name="child">node to add.</param> /// <returns>this element, so that you can add more child nodes or elements.</returns> public Element PrependChild(Node child) { Validate.NotNull(child); AddChildren(0, child); return this; }
internal Node DoClone(Node parent) { Node clone = (Node)this.MemberwiseClone(); clone.parentNode = parent; // can be null, to create an orphan split clone.siblingIndex = parent == null ? 0 : siblingIndex; clone.attributes = attributes != null ? attributes.Clone() : null; clone.baseUri = baseUri; clone.childNodes = new List<Node>(childNodes.Count); foreach (Node child in childNodes) { clone.childNodes.Add(child); } return clone; }
/// <summary> /// Insert the specified node into the DOM after this node (as a following sibling). /// </summary> /// <param name="node">to add after this element</param> /// <returns>this element, for chaining</returns> /// <seealso cref="Before(Node)">Before(Node)</seealso> public override Node After(Node node) { return (Element)base.After(node); }
public void Head(Node node, int depth) { ((Node)node).AppendOuterHtmlHeadTo(accum, depth, @out); }
public void Tail(Node node, int depth) { accum.Append("</" + node.NodeName + ">"); }
public void Tail(Node node, int depth) { if (!node.NodeName.Equals("#text")) { // saves a void hit. ((Node)node).AppendOuterHtmlTailTo(accum, depth, @out); } }
private void InsertNode(Node node) { CurrentElement().AppendChild(node); }
public void Head(Node source, int depth) { if (source is Element) { Element sourceEl = (Element)source; if (this._enclosing.whitelist.IsSafeTag(sourceEl.TagName)) { // safe, clone and copy safe attrs Cleaner.ElementMeta meta = this._enclosing.CreateSafeElement(sourceEl); Element destChild = meta.el; this.destination.AppendChild(destChild); this.numDiscarded += meta.numAttribsDiscarded; this.destination = destChild; } else { if (source != this.root) { // not a safe tag, so don't add. don't count root against discarded. this.numDiscarded++; } } } else { if (source is TextNode) { TextNode sourceText = (TextNode)source; TextNode destText = new TextNode(sourceText.WholeText, source.BaseUri); this.destination.AppendChild(destText); } else { if (source is DataNode && this._enclosing.whitelist.IsSafeTag(source.Parent.NodeName)) { DataNode sourceData = (DataNode)source; DataNode destData = new DataNode(sourceData.WholeData, source.BaseUri); this.destination.AppendChild(destData); } else { // else, we don't care about comments, xml proc instructions, etc this.numDiscarded++; } } } }