2008-10-22

Serving the correct XHTML document type

If you have to use PHP… this seems to work.

<?php

# From: http://randsco.com/index.php/2005/11/10/serving_xhtml_with_the_right_mime_type

$charset = "utf-8";
$mime = "text/html";

# NOTE: To allow for q-values with one space (text/html; q=0.5), 
# use the following regex:
# "/text\/html;[\ ]{0,1}q=([0-1]{0,1}\.\d{0,4})/i"
if((isset($_SERVER["HTTP_ACCEPT"])) && (stristr($_SERVER["HTTP_ACCEPT"],"application/xhtml+xml"))) {
   if(preg_match("/application\/xhtml\+xml;q=([0-1]{0,1}\.\d{0,4})/i",$_SERVER["HTTP_ACCEPT"],$matches)) {
      $xhtml_q = $matches[1];
      if(preg_match("/text\/html;q=([0-1]{0,1}\.\d{0,4})/i",$_SERVER["HTTP_ACCEPT"],$matches)) {
         $html_q = $matches[1];
         if((float)$xhtml_q >= (float)$html_q)
            $mime = "application/xhtml+xml";
      }
   }
   else
    $mime = "application/xhtml+xml";
}

# special check for the W3C_Validator
# (allows IE page validation as XHTMLv1.1)
# but still serves page for IE to "understand" (i.e. text/html)
if (stristr($_SERVER["HTTP_USER_AGENT"],"W3C_Validator")) {
  $mime = "application/xhtml+xml";
}

# set the prolog_type according to the mime type which was determined
if($mime == "application/xhtml+xml") { 
  $prolog_type  = '<?xml version="1.0" encoding="'.$charset.'" ?>'."\n";
  $prolog_type .= '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" ';
  $prolog_type .= '"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">'."\n";
  $prolog_type .= '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">'."\n\n";
} else {
  $prolog_type  = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"';
  $prolog_type .= '"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'."\n";
  $prolog_type .= '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">'."\n\n"; 
}

# output the mime type and prolog type to your page
header("Content-Type: $mime;charset=$charset");
header("Vary: Accept");
print $prolog_type;
?>