public function getXSL(Rendering $rendering)
	{
		$groupedTemplates = [];
		$templates        = $rendering->getTemplates();

		// Replace simple templates if there are at least 3 of them
		TemplateHelper::replaceHomogeneousTemplates($templates, 3);

		// Group tags with identical templates together
		foreach ($templates as $tagName => $template)
		{
			$template = $this->optimizer->optimizeTemplate($template);
			$groupedTemplates[$template][] = $tagName;
		}

		// Declare all the namespaces in use at the top
		$xsl = '<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"';

		// Append the namespace declarations to the stylesheet
		$prefixes = $this->getPrefixes(array_keys($templates));
		if (!empty($prefixes))
		{
			foreach ($prefixes as $prefix)
			{
				$xsl .= ' xmlns:' . $prefix . '="urn:s9e:TextFormatter:' . $prefix . '"';
			}

			/**
			* Exclude those prefixes to keep the HTML neat
			*
			* @link http://lenzconsulting.com/namespaces-in-xslt/#exclude-result-prefixes
			*/
			$xsl .= ' exclude-result-prefixes="' . implode(' ', $prefixes) . '"';
		}

		// Start the stylesheet with the boilerplate stuff
		$xsl .= '><xsl:output method="html" encoding="utf-8" indent="no"/>';

		// Add stylesheet parameters
		foreach ($rendering->getAllParameters() as $paramName => $paramValue)
		{
			$xsl .= $this->writeTag('xsl:param', ['name' => $paramName], htmlspecialchars($paramValue, ENT_NOQUOTES));
		}

		// Add templates
		foreach ($groupedTemplates as $template => $tagNames)
		{
			$xsl .= $this->writeTag('xsl:template', ['match' => implode('|', $tagNames)], $template);
		}

		$xsl .= '</xsl:stylesheet>';

		return $xsl;
	}