PHP's output buffering allows you to register callbacks, that will process the output before returning it back up the stack. This feature is usually used in conjunction with handlers added by PHP or it's extensions such as ob_gzhandler, which gzips the output, or ob_tidyhandler, which passes the output through tidy. As output buffers can be stacked, you can use many handlers in turn using the ob_start function.
<?php
ob_start('ob_gzhandler');
ob_start('ob_tidyhandler');
?>
<!-- Your output here -->
</pre>
Because you can pass ob_start any function name you desire, adding custom handlers is easy. At my current workplace, we needed a quick fix for something we'd overlooked and because we'd (fairly) strictly stuck to generate decent markup, we used an output handler in combination with SimpleXml to manipulate the DOM in our HTML pages. I can't divulge the what we needed to do or the details of how we did it, but here's a basic example that will attempt to insert a CSS link to a page.
<?php
function process_output($buffer)
{
try {
$xml = new SimpleXmlElement($buffer);
if (isset($xml->head)) {
$link = $xml->head->addChild('link');
$link->addAttribute('rel', 'stylesheet');
$link->addAttribute('href', 'http://o.aolcdn.com/dojo/1.0/dojo/resources/dojo.css');
$link->addAttribute('type', 'text/css');
}
return $xml->asXML();
} catch(Exception $e) {
error_log($e->getMessage());
return false;
}
}
ob_start('process_output');
?>
<!-- Your output here -->
This code can be added to a file that's included in every page for a quick fix, but beware of performance hits. A quick test showed adding the above processing dropped this example files performance from 960 requests per second to 795 requests per second.