This is an archive of an inactive wiki and cannot be modified.

Serving Content with two content types

This technique helps implementing CategoryBpContentFormatSupport using PHP.

The Best Practices require that content be served (in the default delivery context) as XHTML Basic. Conformant XHTML Basic content must use the following document type declaration:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.0//EN" 

and be served as application/xhtml+xml.

One of the difficulties with serving content with such a media type is that some desktop browsers (among which unfortunately soem of the most deployed ones) don't recognize it, preventing to serve exactly the same content to mobile and desktop users.

For static content served with Apache, you can fake proper content negotiation using rewrite rules (see an example of these rewrite rules). Note that while this works, it doesn't fully respect the HTTP specification on content negotiation.

Another option is to use Apache's proper content negotiation by having each file that needs to be served as application/xhtml+xml and text/html be available both as .xhtml and .html files (e.g. "foo.xhtml" in parallel with "foo.html" in, which will cause Apache to put them in content negotiation when requesting the corresponding URI without extension (e.g.; content negotiation is enabled through the multiviews option in Apache:

# to be placed in Apache main configuration file or in a local .htaccess
# enabling content negotiation
Options +Multiviews

To avoid duplicating files all over the file system, one could very well use symbolic links on the filesystem to have each .html be an exact copy of the .xhtml files.

For content served through PHP, it is possible to work around this with the following code (to be used before any other content is sent to the user); the said code imports conneg.phi, a small utility library to deal with Content Negotiation parsing.

// Dealing with MIME Type
// Default should be application/xhtml+xml in the DDC
// so we serve application/xhtml+xml unless the client
// says it prefers text/html

$conneg = new contentNegotiation();
$uastring = $_SERVER["HTTP_USER_AGENT"];
// We signal to the client that the content served depends on both the accept header and the user agent string
header("Vary: Accept, User-Agent");
// if the accept headers say that application/xhtml+xml is preferred and the user agent doesn't say Internet Explorer
if ($conneg->compareQ("application/xhtml+xml,text/html")=="application/xhtml+xml" && !strpos($uastring,"MSIE")) {
  echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.0//EN" "">';

} else {
  echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "">';

(Writing a similar system in other dynamic languages is fairly straightforward)

Back to BestPracticesList


Contributions to this wiki are governed by the W3C policies for Contribution to W3C' wiki on Mobile Web.