public function generate($indent = false, $tab_depth = 0, $has_parent = false)
    {
        $result = null;
        $newline = ($indent ? PHP_EOL : null);

        if (!$has_parent) {
            if ($this->_includeHeader) {
                $result .= sprintf(
                    '<?xml version="%s" encoding="%s" ?>%s',
                    $this->_version,
                    $this->_encoding,
                    $newline
                );
            }

            if ($this->_dtd) {
                $result .= $this->_dtd . $newline;
            }

            if (is_array($this->_processingInstructions) && !empty($this->_processingInstructions)) {
                $result .= implode(PHP_EOL, $this->_processingInstructions);
            }
        }

        $result .= ($indent ? str_repeat("\t", $tab_depth) : null) . '<' . $this->getName();

        $attributes = $this->getAttributes();

        if (!empty($attributes)) {
            foreach ($attributes as $attribute => $value) {
                $length = strlen($value);
                if ($length !== 0 || $length === 0 && $this->_allowEmptyAttributes) {
                    $result .= sprintf(' %s="%s"', $attribute, $value);
                }
            }
        }

        $value = $this->getValue();
        $added_newline = false;

        if ($this->getNumberOfChildren() > 0 || strlen($value) !== 0 || !$this->_selfclosing) {
            $result .= '>';

            foreach ($this->_children as $i => $child) {
                if (!($child instanceof XMLElement)) {
                    $result .= $child;
                } else {
                    if ($added_newline === false) {
                        $added_newline = true;
                        $result .= $newline;
                    }

                    $child->setElementStyle($this->_elementStyle);
                    $result .= $child->generate($indent, $tab_depth + 1, true);
                }
            }

            $result .= sprintf(
                "%s</%s>%s",
                ($indent && $added_newline ? str_repeat("\t", $tab_depth) : null),
                $this->getName(),
                $newline
            );

            // Empty elements:
        } else {
            if ($this->_elementStyle === 'xml') {
                $result .= ' />';
            } elseif (in_array($this->_name, XMLElement::$no_end_tags) || (substr($this->getName(), 0, 3) === '!--')) {
                $result .= '>';
            } else {
                $result .= sprintf("></%s>", $this->getName());
            }

            $result .= $newline;
        }

        return $result;
    }