Veröffentlicht am Samstag, 31. Januar 2009, von infinity auf Alphane Moon
Beim Einsatz von XHTML kann man viele Überraschungen erleben. Ich verwende zum Beispiel auf jeder Seite SVG, das inline in das Markup eingebettet ist. Damit die Grafiken im Browser auch zu sehen sind, muß die Seite mit dem richtigen MIME-Type ausgeliefert werden: application/xhtml+xml. Der für normale HTML-Seiten übliche MIME-Type text/html funktioniert nicht, das ist jedoch der einzige, den der Internet Explorer versteht. Eine Lösung muß gefunden werden: eine Content Negotiation, die auf dem ACCEPT-Header basiert.
XHTML muß in manchen Fällen mit einem bestimmten MIME-Type ausgeliefert werden. Das kann man ja irgendwie einstellen. Warum ist das ganze eigentlich ein Problem? Das Problem liegt darin, daß der Internet Explorer mit dem benötigten MIME-Type application/xhtml+xml nichts anfangen kann. Ich kann mir das auch nicht erklären, warum das so ist, denn andere Browser haben damit keine gravierenden Schwierigkeiten.

Je nach den verwendeten Sicherheitseinstellungen zeigt der Internet Explorer ein faszinierend unerwartetes Verhalten: Es erscheint ein Download-Prompt oder eine Fehlermeldung. Beiden ist gemeinsam, daß die XHTML-Seite überhaupt nicht angezeigt wird.

Whoa, sind die schön! Mausgraue Download-Pop-Ups und Fehlermeldungen. Na, wenn das mal beim Besucher kein tiefes Vertrauen weckt! Da fragt man sich manchmal schon, ob das nicht Sabotage ist. Auch der neue Internet Explorer 8 kann es nicht besser. Schrecklich.
Die meisten User-Agents und Browser senden bei einem Request einen ACCEPT-Header an den Server. Er enthält Informationen darüber, welche Dateiarten überhaupt akzeptiert werden.
Der ACCEPT-Header von Opera enthält zum Beispiel folgendes:
text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1
Der q-Wert aus dem ACCEPT-Header ist eine Zahl zwischen 0.0 und 1.0. Er beschreibt die besonderen Vorlieben eines User-Agents für bestimmte MIME-Typen.
Die Tatsache, daß ein Browser in der Regel einen ACCEPT-Header sendet, kann man für eine Content Negotiation ausnutzen.
Die einfachste Variante einer Content Negotiation mit PHP ist ziemlich geradeaus: Es wird überprüft, ob die Zeichenkette application/xhtml+xml im HTTP_ACCEPT vorkommt. Ist das der Fall, wird mit der Funktion header() der entsprechende MIME-Type ausgegeben.
<?php
if (stristr($_SERVER["HTTP_ACCEPT"],"application/xhtml+xml") ) {
header("Content-type: application/xhtml+xml"; charset=UTF-8");
}
else {
header("Content-type: text/html"; charset=UTF-8");
}
?>
Eine ausgefeiltere Umsetzung berücksichtigt den q-Wert aus dem ACCEPT-Header:
<?php
$charset = "UTF-8";
$mime = "text/html";
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(stristr(getenv('HTTP_USER_AGENT'), "W3C_Validator")){
$mime = "application/xhtml+xml";
}
header("Content-Type: $mime; charset=$charset");
header("Vary: Accept");
?>
Auch für den Markup-Validator des W3C wird bei der zweiten Umsetzung der MIME-Type auf application/xhtml+xml gesetzt. Der ACCEPT-Header des Validators ist leer, über seinen User-Agent-String W3C_Validator kann man ihn trotzdem identifizieren. Und wenn sich nun ein User-Agent als Validator ausgibt, aber kein application/xhtml+xml versteht? Ja, dann hat er eben Pech gehabt. So it goes.
Falls man statische .xhtml-Dateien in Abhängigkeit vom ACCEPT-Header als text/html oder application/xhtml+xml losschicken möchte, kann man auch über die Datei .htaccess des Apache-Webservers eine Content Negotiation einrichten:
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_ACCEPT} application/xhtml\+xml
RewriteCond %{HTTP_ACCEPT} !application/xhtml\+xml\s*;\s*q=0
RewriteCond %{REQUEST_URI} \.xhtml$
RewriteCond %{THE_REQUEST} HTTP/1\.1
RewriteRule .* - [T=application/xhtml+xml]
all content copyright © 2007-2010 Alphane Moon