diff --git a/lib/SimpleSAML/Utilities.php b/lib/SimpleSAML/Utilities.php index 6a0f174afa7e0b206549bc784c26f943179a7fcb..3521511b24ca406cd08d46c935d9efc6da5be8b0 100644 --- a/lib/SimpleSAML/Utilities.php +++ b/lib/SimpleSAML/Utilities.php @@ -1541,6 +1541,90 @@ class SimpleSAML_Utilities { return $ret; } + + /** + * Format a DOM element. + * + * This function takes in a DOM element, and inserts whitespace to make it more + * readable. Note that whitespace added previously will be removed. + * + * @param DOMElement $root The root element which should be formatted. + * @param string $indentBase The indentation this element should be assumed to + * have. Default is an empty string. + */ + public static function formatDOMElement(DOMElement $root, $indentBase = '') { + assert(is_string($indentBase)); + + /* Check what this element contains. */ + $fullText = ''; /* All text in this element. */ + $textNodes = array(); /* Text nodes which should be deleted. */ + $childNodes = array(); /* Other child nodes. */ + for ($i = 0; $i < $root->childNodes->length; $i++) { + $child = $root->childNodes->item($i); + + if($child instanceof DOMText) { + $textNodes[] = $child; + $fullText .= $child->wholeText; + + } elseif ($child instanceof DOMComment || $child instanceof DOMElement) { + $childNodes[] = $child; + + } else { + /* Unknown node type. We don't know how to format this. */ + return; + } + } + + $fullText = trim($fullText); + if (strlen($fullText) > 0) { + /* We contain text. */ + $hasText = TRUE; + } else { + $hasText = FALSE; + } + + $hasChildNode = (count($childNodes) > 0); + + if ($hasText && $hasChildNode) { + /* Element contains both text and child nodes - we don't know how to format this one. */ + return; + } + + /* Remove text nodes. */ + foreach ($textNodes as $node) { + $root->removeChild($node); + } + + if ($hasText) { + /* Only text - add a single text node to the element with the full text. */ + $root->appendChild(new DOMText($fullText)); + return; + + } + + if (!$hasChildNode) { + /* Empty node. Nothing to do. */ + return; + } + + /* Element contains only child nodes - add indentation before each one, and + * format child elements. + */ + $childIndentation = $indentBase . ' '; + foreach ($childNodes as $node) { + /* Add indentation before node. */ + $root->insertBefore(new DOMText("\n" . $childIndentation), $node); + + /* Format child elements. */ + if ($node instanceof DOMElement) { + self::formatDOMElement($node, $childIndentation); + } + } + + /* Add indentation before closing tag. */ + $root->appendChild(new DOMText("\n" . $indentBase)); + } + } ?> \ No newline at end of file