Helper function to recursively sanitize nodes

@param $node DOMNode The node to sanitize
329648
private function sanitizeNode(DOMNode $node)
    {
        // Traverse the nodes, without foreach because nodes may be removed
        $child = (!empty($node->childNodes) && $node->childNodes->length > 0) ? $node->childNodes->item(0) : null;
        while ($child !== null)
        {
            $tag = $child->nodeName;

            // Allow text nodes
            if ($tag === "#text")
            {
                $child = $child->nextSibling;
                continue;
            }

            if (isset($this->remove_tags[$tag]))
            {
                // Tag is on the list of nodes to fully remove including child nodes
                $remove = $child;
                $child = $child->nextSibling;
                $node->removeChild($remove);
            }
            elseif (!isset($this->allowed_tags[$tag]))
            {
                // Add the child nodes of the disalowed tag to the parent node in its place,
                // and move the pointer to the first inserted child node, or the next node.
                $child = $this->unwrapContents($node, $child);
            }
            else
            {
                // Sanitize the attributes of an allowed tag
                if ($child->attributes !== null)
                    $this->sanitizeAttributes($child);

                // And now process the contents
                $this->sanitizeNode($child);

                // Finally, call a callback if applicable
                if (isset($this->tag_callback[$tag]))
                    $this->tag_callback[$tag]($child);

                $child = $child->nextSibling;
            }
        }
    }
1269653
public function node(\DOMNode $node) {
        // A listing of types is at http://php.net/manual/en/dom.constants.php
        switch ($node->nodeType) {
            case XML_ELEMENT_NODE:
                $this->rules->element($node);
                break;
            case XML_TEXT_NODE:
                $this->rules->text($node);
                break;
            case XML_CDATA_SECTION_NODE:
                $this->rules->cdata($node);
                break;
            // FIXME: It appears that the parser doesn't do PI's.
            case XML_PI_NODE:
                $this->rules->processorInstruction($node);
                break;
            case XML_COMMENT_NODE:
                $this->rules->comment($node);
                break;
            // Currently we don't support embedding DTDs.
            default:
                print '<!-- Skipped -->';
                break;
        }
    }
551360
protected function checkContext(DOMNode $node)
	{
		// Test whether we know in what context this node is used. An <xsl:for-each/> ancestor would // change this node's context
		$xpath     = new DOMXPath($node->ownerDocument);
		$ancestors = $xpath->query('ancestor::xsl:for-each', $node);

		if ($ancestors->length)
		{
			throw new UnsafeTemplateException("Cannot assess context due to '" . $ancestors->item(0)->nodeName . "'", $node);
		}
	}
832093
protected function reloadDocument($node = null)
    {
        $reloadDocument = new ReloadDocument();
        if ($node) {
            $reloadDocument->setNode($node);
        }

        $this->feedbackCollection->add($reloadDocument);
    }
610156
private function ensureNodeClass(DOMNode $node)
    {
        $class = $this->nodeClasses['DOMElement'];

        if (true !== ($node instanceof $class) && $node instanceof \DOMElement) {
            return $node->ownerDocument->importNode($node, true);
        }

        return $node;
    }
458582
public function enterNode(Node $node)
    {
        if ($node instanceof Namespace_) {
            // If this is the same namespace as last namespace, let's do ourselves
            // a favor and reload all the aliases...
            if (\strtolower($node->name) === \strtolower($this->lastNamespace)) {
                $this->aliases = $this->lastAliases;
            }
        }
    }
1234562
public static function remove_node($node) {
		if (
			! \is_a($node, 'DOMElement') &&
			! \is_a($node, 'DOMNode')
		) {
			return false;
		}

		$node->parentNode->removeChild($node);

		return true;
	}
641858
public function removeNode( $node )
	{
		foreach( $this->getNodes() as $_node )
			$this->removeEdge( $_node, $node );									//  remove all Edges of Node
		$this->nodeSet->removeNode( $node );									//  remove Node
	}
260971
public function leaveNode(Node $node)
    {
        if ($node instanceof Stmt\Use_
            || $node instanceof Stmt\GroupUse
        ) {
            return false;
        }
    }
380382
function cleanNode(node)
			{
				var child = node.firstChild;
				
				while (child != null)
				{
					var next = child.nextSibling;
					cleanNode(child);
					child = next;
				}
				
				if ((node.nodeType != 1 || (node.nodeName !== 'BR' && node.firstChild == null)) &&
					(node.nodeType != 3 || mxUtils.trim(mxUtils.getTextContent(node)).length == 0))
				{
					node.parentNode.removeChild(node);
				}
				else
				{
					// Removes linefeeds
					if (node.nodeType == 3)
					{
						mxUtils.setTextContent(node, mxUtils.getTextContent(node).replace(/\n|\r/g, ''));
					}

					// Removes CSS classes and styles (for Word and Excel)
					if (node.nodeType == 1)
					{
						node.removeAttribute('style');
						node.removeAttribute('class');
						node.removeAttribute('width');
						node.removeAttribute('cellpadding');
						node.removeAttribute('cellspacing');
						node.removeAttribute('border');
					}
				}
			}
837965
public function _cleanStyles($node)
    {
        if (property_exists($node, 'tagName') && $node->tagName === 'svg') {
            return;
        }

        // Do not bother if there's no method to remove an attribute
        if (method_exists($node, 'removeAttribute')) {
            $presentational_attributes = ['align', 'background', 'bgcolor', 'border', 'cellpadding', 'cellspacing', 'frame', 'hspace', 'rules', 'style', 'valign', 'vspace'];
            // Remove `style` and deprecated presentational attributes
            foreach ($presentational_attributes as $presentational_attribute) {
                $node->removeAttribute($presentational_attribute);
            }

            $deprecated_size_attribute_elems = ['table', 'th', 'td', 'hr', 'pre'];
            if (property_exists($node, 'tagName') && in_array($node->tagName, $deprecated_size_attribute_elems)) {
                $node->removeAttribute('width');
                $node->removeAttribute('height');
            }
        }

        $cur = $node->firstChild;
        while ($cur !== null) {
            $this->_cleanStyles($cur);
            $cur = $cur->nextSibling;
        }
    }
807223
public function remove($node)
    {
        $nodeIndex = null;
        $nodeString = serialize($node);

        // Search for the node in the node list
        foreach (array_keys($this->_nodes) as $i) {
            if ($this->_nodes[$i]['n'] === $node) {
                $nodeIndex = $i;
                break;
            }
        }

        if (is_null($nodeIndex)) {
            throw new InvalidArgumentException('Node was not in the hash');
        }

        // Remove all points from the circle
        $numberOfReplicas = (int)($this->_nodes[$nodeIndex]['w'] * $this->_numberOfReplicas);
        for ($i = 0; $i < $numberOfReplicas; $i++) {
            unset($this->_circle[$this->hash($nodeString . $i)]);
        }
        $this->_updateCircle();

        // Unset the node from the node list
        unset($this->_nodes[$nodeIndex]);
        $this->_nodeCount--;
    }
134015
protected function removeSpaceBefore(Node $node) {
    $prev = $node->previousToken();
    if ($prev instanceof WhitespaceNode) {
      $prev->remove();
    }
  }
1217361
private function cleanKey($node, $key)
    {
        if ($key === '') {
            $key = $node ? (string) count($node) : 0;
            // Found a [] key, so track this to ensure that we disable numeric
            // indexing of keys in the resolved query aggregator.
            $this->numericIndices = false;
        }

        return $key;
    }
1129518
protected function getNodeDepth(DomNode $node)
    {
        // initial depth for top level elements (to avoid "ifs")
        $depth = -2;

        while ($node) {
            ++$depth;
            $node = $node->parentNode;
        }

        return $depth;
    }
709949
protected function normalizeNode(DOMNode $node)
	{
		if (!$node->parentNode)
		{
			// Ignore nodes that have been removed from the document
			return;
		}
		if ($node instanceof DOMElement)
		{
			$this->normalizeElement($node);
		}
		elseif ($node instanceof DOMAttr)
		{
			$this->normalizeAttribute($node);
		}
	}
380344
private function sanitizeAttributes(DOMNode $child)
    {
        // Compile a list of attributes that should be removed
        $remove_attributes = array();
        foreach ($child->attributes as $attrib)
        {
            $name = $attrib->name;
            if (!isset($this->allowed_attributes[$name]))
            {
                $remove_attributes[] = $attrib;
            }
            elseif ($name === "href")
            {
                $val = $attrib->nodeValue;

                $is_allowed = false;
                $proto_pos = strpos($val, ":");
                if ($proto_pos !== false)
                {
                    $proto = strtolower(substr($val, 0, $proto_pos));
                    if (isset($this->allowed_protocols[$proto]))
                        $is_allowed = true;
                }
                elseif (substr($val, 0, 2) === '//')
                { // External link with same protocol
                    if (isset($this->allowed_protocols['https']))
                        $is_allowed = true;
                }
                else 
                { // Internal link
                    $is_allowed = true;
                }

                if (!$is_allowed)
                    $remove_attributes[] = $attrib;
            }
        }

        // Remove all nodes selected for removal
        foreach ($remove_attributes as $attrib)
            $child->removeAttributeNode($attrib);
    }