Send the Correct Doctype

Posted: August 04, 2007
Categories: (X)HTML, PHP

Most web pages that use XHTML lose some of the advantages offered by that format because they do not send the correct content type header. This article explains a simple way to send the correct headers using PHP to avoid problems with browsers that do not support XML.

First, I will explain why you should send the proper content type header and why you should not always send "text/xhtml+xml." One of the advantages of XML is that the user agent is required to check the document for "well formedness." If the file is sent as text/html (most are), the browser might not check the file. This can lead to hidden problems and incompatible behavior. When a web browser downloads a page, it checks the HTTP headers for the type of file. Just putting the <!DOCTYPE> tag in the file is not good enough. The content type sent by the server will override the doctype listed in the file. You could set up the server to send html files as text/xhtml+xml, but Internet Explorer and most older browsers do not accept that content type. So how do you know what to send?

You could configure your web server to use content negotiation based on the accept header sent by the browser, but that can be difficult to set up and does not offer the flexibility that you can get with PHP. On my site, I use code similar to the following:

header('Vary: Accept');
$XML = false;
if (array_key_exists('HTTP_ACCEPT', $_SERVER) &&
    stristr($_SERVER['HTTP_ACCEPT'], 'application/xhtml+xml')) $XML = true;

// the W3C Validator does not send the "accept: application/xhtml+xml" header
// send it XML anyway so that XHTML will be validated instead of HTML
if (array_key_exists('HTTP_USER_AGENT', $_SERVER) &&
    stristr($_SERVER['HTTP_USER_AGENT'], 'W3C_Validator')) $XML = true;

if ($XML) {
  header('Content-Type: application/xhtml+xml; charset=utf-8');
else {
  header('Content-Type: text/html; charset=utf-8');