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;
            }
        }
    }