public function parse($strOutputFormat, $blnFailIfNotFound = false)
    {
        if ($this->strTemplate == '') {
            return '';
        }

        // Set the format.
        $this->strFormat = $strOutputFormat;

        // HOOK: add custom parse filters.
        $this->callParseTemplateHook();

        $strBuffer = '';

        // Start with the template itself
        $this->strParent = $this->strTemplate;

        // Include the parent templates
        while ($this->strParent !== null) {
            $strCurrent = $this->strParent;
            $strParent  = $this->strDefault
                ?: $this->getTemplate($this->strParent, $this->strFormat, $blnFailIfNotFound);

            // Check if we have the template.
            if (empty($strParent)) {
                return sprintf(
                    'Template %s not found (it is maybe within a unreachable theme folder?).',
                    $this->strParent
                );
            }

            // Reset the flags
            $this->strParent  = null;
            $this->strDefault = null;

            ob_start();
            include($strParent);

            // Capture the output of the root template
            if ($this->strParent === null) {
                $strBuffer = ob_get_contents();
            } elseif ($this->strParent == $strCurrent) {
                $this->strDefault = $this->getTemplate($this->strParent, $this->strFormat, $blnFailIfNotFound);
            }

            ob_end_clean();
        }

        // Reset the internal arrays
        $this->arrBlocks = array();

        // Add start and end markers in debug mode
        if (\Config::get('debugMode') && in_array($this->strFormat, ['html5', 'xhtml'])) {
            $strRelPath = str_replace(TL_ROOT . '/', '', $this->getTemplate($this->strTemplate, $this->strFormat));
            $strBuffer  = <<<EOF
<!-- TEMPLATE START: $strRelPath -->
$strBuffer
<!-- TEMPLATE END: $strRelPath -->

EOF;
        }

        return $strBuffer;
    }