thought-afterGeeky stuff by Lafinboy

Oh hai! is published by Lafinboy, aka Scott Swabey, a self confessed geek, standards compliant web developer, OOP afflicted code monkey, loving father and husband. These are (some of) his thoughts.

Working with XHTML is all very commendable, but if the default (read wrong) MIME type is sent to the UA then you are still only sending HTML documents out to browserland. If this is the case you may as well work with the HTML doctype. So how do you send the correct MIME type for XHTML?

There are various methods depending on your situation. One can configure the server to send the correct MIME type based on file type, use httpd or htaccess files, or force the correct MIME type through the header of the page using your favourite server side code (ASP, PHP, .NET, et al). There's just one problem though – Internet Explorer currently doesn't support documents served with the

application/xhtml+xml MIME type. This is where we need to perform a negotiation between the server and browser about the media types the browser can accept, and which one it prefers.The basics of content negotiation are:

  1. Server says hello to the browser, and ask if it can send it a page
  2. Browser says hi back, and tells the server what media types it can accept, and of those which is it's preferred media type
  3. Server get's the document in the browsers preferred format and send it out
  4. Browser displays our correctly formatted page

So by evaluating the media types and relative weighting of each type we can determine whether the browser shoud be sent files as text/html or application/xhtml+xml.

A sample PHP content negotiation script is shown below:
[code lang="php"]< ?php $charset = "utf-8"; $mime = "text/html"; function xml2html($buffer) { return (preg_replace("!\s*/>!", ">", $buffer));
if(stristr($_SERVER["HTTP_ACCEPT"],"application/xhtml+xml")) {
if(preg_match("/application\/xhtml\+xml;q=([01]|0\.\d{1,3}|1\.0)/i", $_SERVER["HTTP_ACCEPT"], $matches)) {
$xhtml_q = $matches[1];
if(preg_match("/text\/html;q=q=([01]|0\.\d{1,3}|1\.0)/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";
if($mime == "application/xhtml+xml") {
$prolog_type = "< ?xml version=\"1.0\" encoding=\"$charset\" ?>\n< !DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"\">\n\n";
$meta_content = "\n";
} else {
$prolog_type = "< !DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Strict//EN\" \"\">\n\n";
$meta_content = "\n";
header("Content-Type: $mime;charset=$charset");
header("Vary: Accept");
print $prolog_type;

This entry was posted by Lafinboy in browsers, Content Negotiation, HTML, MIME Types, PHP, XHTML and tagged , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

Browse by Topic

Email Me