Deprecated: Creation of dynamic property wpdb::$categories is deprecated in /homepages/34/d43362328/htdocs/ydontu/blog/wp-includes/wp-db.php on line 668

Deprecated: Creation of dynamic property wpdb::$post2cat is deprecated in /homepages/34/d43362328/htdocs/ydontu/blog/wp-includes/wp-db.php on line 668

Deprecated: Creation of dynamic property wpdb::$link2cat is deprecated in /homepages/34/d43362328/htdocs/ydontu/blog/wp-includes/wp-db.php on line 668

Deprecated: Return type of WP_Theme::offsetExists($offset) should either be compatible with ArrayAccess::offsetExists(mixed $offset): bool, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /homepages/34/d43362328/htdocs/ydontu/blog/wp-includes/class-wp-theme.php on line 554

Deprecated: Return type of WP_Theme::offsetGet($offset) should either be compatible with ArrayAccess::offsetGet(mixed $offset): mixed, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /homepages/34/d43362328/htdocs/ydontu/blog/wp-includes/class-wp-theme.php on line 595

Deprecated: Return type of WP_Theme::offsetSet($offset, $value) should either be compatible with ArrayAccess::offsetSet(mixed $offset, mixed $value): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /homepages/34/d43362328/htdocs/ydontu/blog/wp-includes/class-wp-theme.php on line 535

Deprecated: Return type of WP_Theme::offsetUnset($offset) should either be compatible with ArrayAccess::offsetUnset(mixed $offset): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /homepages/34/d43362328/htdocs/ydontu/blog/wp-includes/class-wp-theme.php on line 544

Deprecated: Using ${var} in strings is deprecated, use {$var} instead in /homepages/34/d43362328/htdocs/ydontu/blog/wp-includes/comment-template.php on line 1739

Deprecated: wp_getimagesize(): Implicitly marking parameter $image_info as nullable is deprecated, the explicit nullable type must be used instead in /homepages/34/d43362328/htdocs/ydontu/blog/wp-includes/media.php on line 5006

Deprecated: Return type of WP_REST_Request::offsetExists($offset) should either be compatible with ArrayAccess::offsetExists(mixed $offset): bool, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /homepages/34/d43362328/htdocs/ydontu/blog/wp-includes/rest-api/class-wp-rest-request.php on line 960

Deprecated: Return type of WP_REST_Request::offsetGet($offset) should either be compatible with ArrayAccess::offsetGet(mixed $offset): mixed, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /homepages/34/d43362328/htdocs/ydontu/blog/wp-includes/rest-api/class-wp-rest-request.php on line 980

Deprecated: Return type of WP_REST_Request::offsetSet($offset, $value) should either be compatible with ArrayAccess::offsetSet(mixed $offset, mixed $value): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /homepages/34/d43362328/htdocs/ydontu/blog/wp-includes/rest-api/class-wp-rest-request.php on line 992

Deprecated: Return type of WP_REST_Request::offsetUnset($offset) should either be compatible with ArrayAccess::offsetUnset(mixed $offset): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /homepages/34/d43362328/htdocs/ydontu/blog/wp-includes/rest-api/class-wp-rest-request.php on line 1003

Deprecated: Return type of WP_Block_List::current() should either be compatible with Iterator::current(): mixed, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /homepages/34/d43362328/htdocs/ydontu/blog/wp-includes/class-wp-block-list.php on line 151

Deprecated: Return type of WP_Block_List::next() should either be compatible with Iterator::next(): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /homepages/34/d43362328/htdocs/ydontu/blog/wp-includes/class-wp-block-list.php on line 175

Deprecated: Return type of WP_Block_List::key() should either be compatible with Iterator::key(): mixed, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /homepages/34/d43362328/htdocs/ydontu/blog/wp-includes/class-wp-block-list.php on line 164

Deprecated: Return type of WP_Block_List::valid() should either be compatible with Iterator::valid(): bool, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /homepages/34/d43362328/htdocs/ydontu/blog/wp-includes/class-wp-block-list.php on line 186

Deprecated: Return type of WP_Block_List::rewind() should either be compatible with Iterator::rewind(): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /homepages/34/d43362328/htdocs/ydontu/blog/wp-includes/class-wp-block-list.php on line 138

Deprecated: Return type of WP_Block_List::offsetExists($index) should either be compatible with ArrayAccess::offsetExists(mixed $offset): bool, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /homepages/34/d43362328/htdocs/ydontu/blog/wp-includes/class-wp-block-list.php on line 75

Deprecated: Return type of WP_Block_List::offsetGet($index) should either be compatible with ArrayAccess::offsetGet(mixed $offset): mixed, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /homepages/34/d43362328/htdocs/ydontu/blog/wp-includes/class-wp-block-list.php on line 89

Deprecated: Return type of WP_Block_List::offsetSet($index, $value) should either be compatible with ArrayAccess::offsetSet(mixed $offset, mixed $value): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /homepages/34/d43362328/htdocs/ydontu/blog/wp-includes/class-wp-block-list.php on line 110

Deprecated: Return type of WP_Block_List::offsetUnset($index) should either be compatible with ArrayAccess::offsetUnset(mixed $offset): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /homepages/34/d43362328/htdocs/ydontu/blog/wp-includes/class-wp-block-list.php on line 127

Deprecated: Return type of WP_Block_List::count() should either be compatible with Countable::count(): int, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /homepages/34/d43362328/htdocs/ydontu/blog/wp-includes/class-wp-block-list.php on line 199

Deprecated: Jetpack::setup_xmlrpc_handlers(): Implicitly marking parameter $xmlrpc_server as nullable is deprecated, the explicit nullable type must be used instead in /homepages/34/d43362328/htdocs/ydontu/blog/wp-content/plugins/jetpack/class.jetpack.php on line 939

Deprecated: Automattic\Jetpack\Connection\Manager::setup_xmlrpc_handlers(): Implicitly marking parameter $xmlrpc_server as nullable is deprecated, the explicit nullable type must be used instead in /homepages/34/d43362328/htdocs/ydontu/blog/wp-content/plugins/jetpack/vendor/automattic/jetpack-connection/src/class-manager.php on line 110

Deprecated: Creation of dynamic property Automattic\Jetpack\Connection\Manager::$error_handler is deprecated in /homepages/34/d43362328/htdocs/ydontu/blog/wp-content/plugins/jetpack/vendor/automattic/jetpack-connection/src/class-manager.php on line 80

Deprecated: Creation of dynamic property WPCOM_REST_API_V2_Endpoint_Instagram_Gallery::$is_wpcom is deprecated in /homepages/34/d43362328/htdocs/ydontu/blog/wp-content/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/class-wpcom-rest-api-v2-endpoint-instagram-gallery.php on line 23

Deprecated: Creation of dynamic property WPCOM_REST_API_V2_Endpoint_Mailchimp::$wpcom_is_wpcom_only_endpoint is deprecated in /homepages/34/d43362328/htdocs/ydontu/blog/wp-content/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/class-wpcom-rest-api-v2-endpoint-mailchimp.php on line 17

Deprecated: Creation of dynamic property WPCOM_REST_API_V2_Endpoint_Tweetstorm_Gather::$wpcom_is_wpcom_only_endpoint is deprecated in /homepages/34/d43362328/htdocs/ydontu/blog/wp-content/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/class-wpcom-rest-api-v2-endpoint-tweetstorm-gather.php on line 21

Deprecated: Creation of dynamic property WPCOM_REST_API_V2_Endpoint_Tweetstorm_Gather::$is_wpcom is deprecated in /homepages/34/d43362328/htdocs/ydontu/blog/wp-content/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/class-wpcom-rest-api-v2-endpoint-tweetstorm-gather.php on line 22

Deprecated: Creation of dynamic property WPCOM_REST_API_V2_Endpoint_Gutenberg_Available_Extensions::$wpcom_is_site_specific_endpoint is deprecated in /homepages/34/d43362328/htdocs/ydontu/blog/wp-content/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/gutenberg-available-extensions.php on line 20

Deprecated: Creation of dynamic property WPCOM_REST_API_V2_Endpoint_Memberships::$wpcom_is_wpcom_only_endpoint is deprecated in /homepages/34/d43362328/htdocs/ydontu/blog/wp-content/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/memberships.php on line 23

Deprecated: Creation of dynamic property WPCOM_REST_API_V2_Endpoint_Memberships::$wpcom_is_site_specific_endpoint is deprecated in /homepages/34/d43362328/htdocs/ydontu/blog/wp-content/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/memberships.php on line 24

Deprecated: Creation of dynamic property WPCOM_REST_API_V2_Endpoint_Subscribers::$wpcom_is_wpcom_only_endpoint is deprecated in /homepages/34/d43362328/htdocs/ydontu/blog/wp-content/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/subscribers.php on line 15

Deprecated: Using ${var} in strings is deprecated, use {$var} instead in /homepages/34/d43362328/htdocs/ydontu/blog/wp-content/plugins/jetpack/extensions/blocks/podcast-player/podcast-player.php on line 157

Deprecated: Using ${var} in strings is deprecated, use {$var} instead in /homepages/34/d43362328/htdocs/ydontu/blog/wp-content/plugins/jetpack/extensions/blocks/podcast-player/podcast-player.php on line 157

Deprecated: Creation of dynamic property Automattic\Jetpack\Sync\Queue::$random_int is deprecated in /homepages/34/d43362328/htdocs/ydontu/blog/wp-content/plugins/jetpack/vendor/automattic/jetpack-sync/src/class-queue.php on line 38

Deprecated: Creation of dynamic property Automattic\Jetpack\Sync\Queue::$random_int is deprecated in /homepages/34/d43362328/htdocs/ydontu/blog/wp-content/plugins/jetpack/vendor/automattic/jetpack-sync/src/class-queue.php on line 38

Deprecated: Using ${var} in strings is deprecated, use {$var} instead in /homepages/34/d43362328/htdocs/ydontu/blog/wp-content/plugins/jetpack/modules/widgets/migrate-to-core/image-widget.php on line 195

Deprecated: Using ${var} in strings is deprecated, use {$var} instead in /homepages/34/d43362328/htdocs/ydontu/blog/wp-content/plugins/jetpack/modules/widgets/migrate-to-core/gallery-widget.php on line 56

Deprecated: Creation of dynamic property Publicize_UI::$in_jetpack is deprecated in /homepages/34/d43362328/htdocs/ydontu/blog/wp-content/plugins/jetpack/modules/publicize.php on line 53

Deprecated: Using ${var} in strings is deprecated, use {$var} instead in /homepages/34/d43362328/htdocs/ydontu/blog/wp-content/plugins/jetpack/modules/calypsoify/class-jetpack-calypsoify.php on line 128

Deprecated: Using ${var} in strings is deprecated, use {$var} instead in /homepages/34/d43362328/htdocs/ydontu/blog/wp-content/plugins/jetpack/modules/calypsoify/class-jetpack-calypsoify.php on line 129

Deprecated: Using ${var} in strings is deprecated, use {$var} instead in /homepages/34/d43362328/htdocs/ydontu/blog/wp-content/plugins/jetpack/modules/calypsoify/class-jetpack-calypsoify.php on line 133

Deprecated: Using ${var} in strings is deprecated, use {$var} instead in /homepages/34/d43362328/htdocs/ydontu/blog/wp-content/plugins/jetpack/modules/calypsoify/class-jetpack-calypsoify.php on line 134

Deprecated: Using ${var} in strings is deprecated, use {$var} instead in /homepages/34/d43362328/htdocs/ydontu/blog/wp-content/plugins/jetpack/modules/calypsoify/class-jetpack-calypsoify.php on line 135

Deprecated: Using ${var} in strings is deprecated, use {$var} instead in /homepages/34/d43362328/htdocs/ydontu/blog/wp-content/plugins/jetpack/modules/simple-payments/simple-payments.php on line 219

Deprecated: Using ${var} in strings is deprecated, use {$var} instead in /homepages/34/d43362328/htdocs/ydontu/blog/wp-content/plugins/jetpack/modules/simple-payments/simple-payments.php on line 220

Deprecated: Using ${var} in strings is deprecated, use {$var} instead in /homepages/34/d43362328/htdocs/ydontu/blog/wp-content/plugins/jetpack/modules/simple-payments/simple-payments.php on line 227

Deprecated: Using ${var} in strings is deprecated, use {$var} instead in /homepages/34/d43362328/htdocs/ydontu/blog/wp-content/plugins/jetpack/modules/simple-payments/simple-payments.php on line 229

Deprecated: Using ${var} in strings is deprecated, use {$var} instead in /homepages/34/d43362328/htdocs/ydontu/blog/wp-content/plugins/jetpack/modules/simple-payments/simple-payments.php on line 231

Deprecated: Using ${var} in strings is deprecated, use {$var} instead in /homepages/34/d43362328/htdocs/ydontu/blog/wp-content/plugins/jetpack/modules/simple-payments/simple-payments.php on line 248

Deprecated: Using ${var} in strings is deprecated, use {$var} instead in /homepages/34/d43362328/htdocs/ydontu/blog/wp-content/plugins/jetpack/modules/simple-payments/simple-payments.php on line 249

Deprecated: Using ${var} in strings is deprecated, use {$var} instead in /homepages/34/d43362328/htdocs/ydontu/blog/wp-content/plugins/jetpack/modules/simple-payments/simple-payments.php on line 267

Deprecated: Using ${var} in strings is deprecated, use {$var} instead in /homepages/34/d43362328/htdocs/ydontu/blog/wp-content/plugins/jetpack/modules/simple-payments/simple-payments.php on line 268

Deprecated: Using ${var} in strings is deprecated, use {$var} instead in /homepages/34/d43362328/htdocs/ydontu/blog/wp-content/plugins/jetpack/modules/simple-payments/simple-payments.php on line 270

Deprecated: Using ${var} in strings is deprecated, use {$var} instead in /homepages/34/d43362328/htdocs/ydontu/blog/wp-content/plugins/jetpack/modules/simple-payments/simple-payments.php on line 271

Deprecated: Using ${var} in strings is deprecated, use {$var} instead in /homepages/34/d43362328/htdocs/ydontu/blog/wp-content/plugins/jetpack/modules/simple-payments/simple-payments.php on line 273

Deprecated: Using ${var} in strings is deprecated, use {$var} instead in /homepages/34/d43362328/htdocs/ydontu/blog/wp-content/plugins/jetpack/modules/simple-payments/simple-payments.php on line 275

Deprecated: Creation of dynamic property WPCOM_Widget_Goodreads::$shelves is deprecated in /homepages/34/d43362328/htdocs/ydontu/blog/wp-content/plugins/jetpack/modules/widgets/goodreads.php on line 33

Deprecated: DateTime::__construct(): Passing null to parameter #1 ($datetime) of type string is deprecated in /homepages/34/d43362328/htdocs/ydontu/blog/wp-includes/script-loader.php on line 348

Deprecated: Creation of dynamic property WP_Block_Type::$plan_check is deprecated in /homepages/34/d43362328/htdocs/ydontu/blog/wp-includes/class-wp-block-type.php on line 333

Deprecated: Creation of dynamic property WP_Block_Type::$plan_check is deprecated in /homepages/34/d43362328/htdocs/ydontu/blog/wp-includes/class-wp-block-type.php on line 333

Deprecated: Creation of dynamic property WP_Block_Type::$plan_check is deprecated in /homepages/34/d43362328/htdocs/ydontu/blog/wp-includes/class-wp-block-type.php on line 333

Deprecated: Creation of dynamic property WP_Block_Type::$plan_check is deprecated in /homepages/34/d43362328/htdocs/ydontu/blog/wp-includes/class-wp-block-type.php on line 333

Deprecated: Creation of dynamic property WP_Block_Type::$plan_check is deprecated in /homepages/34/d43362328/htdocs/ydontu/blog/wp-includes/class-wp-block-type.php on line 333

Deprecated: Creation of dynamic property WP_Block_Type::$plan_check is deprecated in /homepages/34/d43362328/htdocs/ydontu/blog/wp-includes/class-wp-block-type.php on line 333

Deprecated: Creation of dynamic property Jetpack_Shortcode_Unavailable::$shortcodes is deprecated in /homepages/34/d43362328/htdocs/ydontu/blog/wp-content/plugins/jetpack/modules/shortcodes/unavailable.php on line 19

Warning: Cannot modify header information - headers already sent by (output started at /homepages/34/d43362328/htdocs/ydontu/blog/wp-includes/wp-db.php:668) in /homepages/34/d43362328/htdocs/ydontu/blog/wp-includes/rest-api/class-wp-rest-server.php on line 1648

Warning: Cannot modify header information - headers already sent by (output started at /homepages/34/d43362328/htdocs/ydontu/blog/wp-includes/wp-db.php:668) in /homepages/34/d43362328/htdocs/ydontu/blog/wp-includes/rest-api/class-wp-rest-server.php on line 1648

Warning: Cannot modify header information - headers already sent by (output started at /homepages/34/d43362328/htdocs/ydontu/blog/wp-includes/wp-db.php:668) in /homepages/34/d43362328/htdocs/ydontu/blog/wp-includes/rest-api/class-wp-rest-server.php on line 1648

Warning: Cannot modify header information - headers already sent by (output started at /homepages/34/d43362328/htdocs/ydontu/blog/wp-includes/wp-db.php:668) in /homepages/34/d43362328/htdocs/ydontu/blog/wp-includes/rest-api/class-wp-rest-server.php on line 1648

Warning: Cannot modify header information - headers already sent by (output started at /homepages/34/d43362328/htdocs/ydontu/blog/wp-includes/wp-db.php:668) in /homepages/34/d43362328/htdocs/ydontu/blog/wp-includes/rest-api/class-wp-rest-server.php on line 1648

Warning: Cannot modify header information - headers already sent by (output started at /homepages/34/d43362328/htdocs/ydontu/blog/wp-includes/wp-db.php:668) in /homepages/34/d43362328/htdocs/ydontu/blog/wp-includes/rest-api/class-wp-rest-server.php on line 1648

Warning: Cannot modify header information - headers already sent by (output started at /homepages/34/d43362328/htdocs/ydontu/blog/wp-includes/wp-db.php:668) in /homepages/34/d43362328/htdocs/ydontu/blog/wp-includes/rest-api/class-wp-rest-server.php on line 1648

Warning: Cannot modify header information - headers already sent by (output started at /homepages/34/d43362328/htdocs/ydontu/blog/wp-includes/wp-db.php:668) in /homepages/34/d43362328/htdocs/ydontu/blog/wp-includes/rest-api/class-wp-rest-server.php on line 1648
{"id":212,"date":"2006-05-05T21:14:14","date_gmt":"2006-05-05T21:14:14","guid":{"rendered":"http:\/\/www.whydontyou.org.uk\/blog\/2006\/05\/05\/content-negotiation-mirrored-post\/"},"modified":"2007-04-02T22:51:23","modified_gmt":"2007-04-02T21:51:23","slug":"content-negotiation-mirrored-post","status":"publish","type":"post","link":"http:\/\/www.whydontyou.org.uk\/blog\/2006\/05\/05\/content-negotiation-mirrored-post\/","title":{"rendered":"Content Negotiation – Mirrored Post"},"content":{"rendered":"

As mentioned in the last post, there is an excellent article available at http:\/\/www.autisticcuckoo.net\/archive.php?id=2004\/ 11\/03\/ content-negotiation<\/a>, but sadly the author of this article has expressed his disinterest in continuing with his blog. While it is possible that he will continue to pay his hosting fees and continue to re-register the domain name, this is not certain so, to try and at least retain this article we have copied it (verbatim) below.<\/p>\n

Original Source – http:\/\/www.autisticcuckoo.net\/archive.php?id=2004\/11\/03\/content-negotiation<\/a><\/p>\n

We have, for some time, tried to inform people about the fact that there is no point whatsoever in using XHTML<\/abbr> as long as you serve the documents with a text\/html<\/code> media type. For those who still want to use XHTML<\/abbr> and gain at least something<\/em> for some<\/em><\/p>\n

users, we have recommended content negotiation<\/dfn>. On several occasions people have asked us to publish a write-up on how to do that, but there hasn’t been time to sit down and write it. Now, finally, we have tried to whip something together that we hope can serve as a guide.<\/p>\n

What Is Content Negotiation?<\/h2>\n

Content negotiation means that the server in one way or another
\nnegotiates<\/q> with a user agent<\/dfn> (browser, search engine, etc) that requests a document. The negotiation means that the user agent announces which media types (also called content type or MIME<\/acronym> type) it can handle and, optionally, which one it prefers<\/em>. The server then serves the document in the way that best suits the user agent.<\/p>\n

The user agent announces which media types it can handle through a header in the HTTP<\/abbr> request it sends to the server. The header is called Accept<\/code> and can look something like this:<\/p>\n

Accept: text\/xml, application\/xml, application\/xhtml+xml, text\/html;q=0.9, text\/plain;q=0.8, image\/png, image\/jpeg, image\/gif;q=0.2, *\/*;q=0.1<\/samp><\/p>\n

The example is what our instance of Mozilla<\/a> sends. (We have inserted blanks between the media types so that the text will wrap.) Our interest now lies with application\/xhtml+xml<\/code> and<\/p>\n

text\/html;q=0.9<\/code>. The part after the semi-colon, q=0.9<\/code>, is called a quality value<\/dfn> and is a value between 0 and 1, inclusive, with up to three decimal places. The higher the quality value, the more the user agent prefers that media type. If no quality value is specified for a particular media type, it means q=1.0<\/code>. The example thus shows that Mozilla prefers application\/xhtml+xml<\/code> to text\/html<\/code>.<\/p>\n

The usual meaning of content negotiation is that the HTTP<\/abbr> server itself decides which media type the user agent prefers, and then automatically chooses between a number of different documents. Normally the file suffix is used to associate to different media types, so the server might choose between<\/p>\n

index.xhtml<\/samp> and index.html<\/samp>.<\/p>\n

This article describes another type of content negotiation; one that is performed through a server-side script. Most web hosts offer some kind of server-side scripting, usually PHP<\/abbr> or ASP<\/acronym>. Our example uses PHP<\/abbr>, since it is available for more platforms and is open source, while ASP<\/acronym> is Microsoft-specific. We don’t delve into the finer details here, but presume that you are sufficiently familiar with PHP<\/abbr>.<\/p>\n

To round off this explanation of what content negotiation means, we want to emphasise that it’s not merely an issue of deciding which media type<\/em> to send. When you have chosen a media type, you should also serve the document with a content<\/em> that corresponds to the chosen media type. You either serve XHTML<\/abbr> as application\/xhtml+xml<\/code>, or you serve HTML<\/abbr> as text\/html<\/code>.<\/p>\n

About the Examples<\/h2>\n

The code samples in this article are written for PHP<\/abbr> 4.1.0 or higher. For older versions you need to replace $_SERVER<\/code> with $HTTP_SERVER_VARS<\/code>. If the code is executed in a function, you then need to declare the array as a global (global $HTTP_SERVER_VARS;<\/code>).<\/p>\n

This article presumes that the document’s content is marked up as XHTML<\/abbr> 1.1, and that it doesn’t contain anything that cannot be converted into HTML<\/abbr> 4.01 Strict, for instance element from other XML<\/abbr> namespaces, or CDATA<\/code> sections.<\/p>\n

Parsing the Accept Header<\/h2>\n

First of all we need to find out whether or not the user agent supports the application\/xhtml+xml<\/code> media type and, if so, whether it prefers that to text\/html<\/code>.<\/p>\n

    \n
  1. $xhtml = false;<\/code><\/li>\n
  2. if (preg_match('\/application\\\/xhtml\\+xml(;q=(\\d+\\.\\d+))?\/i', $_SERVER['HTTP_ACCEPT'], $matches)) {<\/code><\/li>\n
  3. $xhtmlQ = isset($matches[2]) ? $matches[2] : 1;<\/code><\/li>\n
  4. if (preg_match('\/text\\\/html(;q=(\\d+\\.\\d+))?\/i', $_SERVER['HTTP_ACCEPT'], $matches)) {<\/code><\/li>\n
  5. $htmlQ = isset($matches[2]) ? $matches[2] : 1;<\/code><\/li>\n
  6. $xhtml = ($xhtmlQ >= $htmlQ);<\/code><\/li>\n
  7. } else {<\/code><\/li>\n
  8. $xhtml = true;<\/code><\/li>\n
  9. }<\/code><\/li>\n
  10. }<\/code><\/li>\n<\/ol>\n

    The $xhtml<\/code> variable indicates whether or not we will serve the document as XHTML<\/abbr>. The initial value is false<\/code>, since many older browsers lack support for XHTML<\/abbr>.<\/p>\n

    On line 2 we check whether the Accept<\/code> header contains
    \napplication\/xhtml+xml<\/code> plus an optional quality value. This regular expression isn’t 100% fool-proof, since it doesn’t limit the value range to [0,1], nor does it limit the number of decimal places to 3. For all intents and purposes, however, it doesn’t matter.<\/p>\n

    On line 3 we extract the quality value, if present. If not, we set the quality value for application\/xhtml+xml<\/code> to 1.<\/p>\n

    On lines 4 and 5 we perform the corresponding check for text\/html<\/code>. Line 6 compares the quality values and sets $xhtml=true<\/code> if the user agent prefers application\/xhtml+xml<\/code> to text\/html<\/code>. Line 8 handles the case of a user agent that specifies application\/xhtml+xml<\/code> in the<\/p>\n

    Accept<\/code> header, but not text\/html<\/code>.<\/p>\n

    After these lines of code we thus have a Boolean variable, $xhtml<\/code>, which indicates whether the document will be served as XHTML<\/abbr>.<\/p>\n

    Prepare HTML<\/abbr> Conversion<\/h2>\n

    If the user agent doesn’t support XHTML<\/abbr>, or if it prefers HTML<\/abbr>, we have to convert the document’s content from XHTML<\/abbr> 1.1 to HTML<\/abbr> 4.01. We do this with a simple function:<\/p>\n

      \n
    1. function xml2html($buffer)<\/code><\/li>\n
    2. {<\/code><\/li>\n
    3. $xml = array('\/>', 'xml:lang=');<\/code><\/li>\n
    4. $html = array('>', 'lang=');<\/code><\/li>\n
    5. return str_replace($xml, $html, $buffer);<\/code><\/li>\n
    6. }<\/code><\/li>\n<\/ol>\n

      Lines 3 and 4 declare two arrays, where the elements in the $xml<\/code> array will be replaced by the corresponding element in the $html<\/code> array.<\/p>\n

      On line 5 each occurrence of \/><\/code> is replaced by ><\/code> in the $buffer<\/code> string. At the same time, each occurrence of xml:lang<\/code> is replaced by lang<\/code>.<\/p>\n

      And Finally\u00e2\u20ac\u00a6<\/h2>\n

      Only a few details now remain. If the $xhtml<\/code> variable is true, we need to write the document type declaration for XHTML<\/abbr> 1.1 and a <html><\/code> element with the proper XML<\/abbr> namespace. Most likely we also want to start with an XML<\/abbr><\/p>\n

      declaration, and link to our style sheets through processing instructions.<\/p>\n

      If the user agent doesn’t want XHTML<\/abbr>, we need to write a document type declaration for HTML<\/abbr> 4.01 Strict and a <html><\/code> element without an XML<\/abbr> namespace. Style sheets should be linked through ordinary <link><\/code> elements (or be imported in a <style><\/code> element). Furthermore, we need to instruct the PHP<\/abbr> interpreter to buffer all output to the response stream, and to call our conversion function on the result before sending it back to the user agent.<\/p>\n

      Before we write anything at all, however, we must send a couple of HTTP<\/abbr> headers: one that says which media type we use, and one that informs proxy servers that content negotiation has taken place so that they can consider that in their caching algorithms.<\/p>\n

        \n
      1. if ($xhtml) {<\/code><\/li>\n
      2. header('Content-Type: application\/xhtml+xml; charset=utf-8');<\/code><\/li>\n
      3. header('Vary: Accept');<\/code><\/li>\n
      4. echo '<?xml version=\"1.0\" encoding=\"utf-8\"?>', \"\\n\";<\/code><\/li>\n
      5. echo '<?xml-stylesheet type=\"text\/css\" xhref=\"\/css\/screen.css\" media=\"screen\"?>', \"\\n\";<\/code><\/li>\n
      6. echo '<?xml-stylesheet type=\"text\/css\" xhref=\"\/css\/print.css\" media=\"print\"?>', \"\\n\";<\/code><\/li>\n
      7. echo '<!DOCTYPE html PUBLIC \"-\/\/W3C\/\/DTD XHTML 1.1\/\/EN\" \"http:\/\/www.w3.org\/TR\/xhtml11\/DTD\/xhtml11.dtd\">', \"\\n\";<\/code><\/li>\n
      8. echo '<html xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\" xml:lang=\"en\">', \"\\n\";<\/code><\/li>\n
      9. } else {<\/code><\/li>\n
      10. header('Content-Type: text\/html; charset=utf-8');<\/code><\/li>\n
      11. header('Vary: Accept');<\/code><\/li>\n
      12. ob_start('xml2html');<\/code><\/li>\n
      13. echo '<!DOCTYPE html PUBLIC \"-\/\/W3C\/\/DTD HTML 4.01\/\/EN\" \"http:\/\/www.w3.org\/TR\/html4\/strict.dtd\">', \"\\n\";<\/code><\/li>\n
      14. echo '<html lang=\"en\">', \"\\n\";<\/code><\/li>\n
      15. }<\/code><\/li>\n<\/ol>\n

        Don’t forget to link to the style sheets in the <head><\/code> if the document is served as HTML<\/abbr>.<\/p>\n

        There is a blatant shortcoming in the example shown in this article: the W3C validator<\/a>. It doesn’t send application\/xhtml+xml<\/code> in its Accept<\/code><\/p>\n

        header, so it’s impossible to validate the document as XHTML<\/abbr>. It is trivial to let a query parameter control the choice of media type, but that is left as an exercise for the reader.<\/p><\/blockquote>\n

        (note: We are aware of some possible copyright issues, and we have attempted to contact the original owner to get permission to repost it verbatim here. At the time of this post, no replies had been received and we can only assume the original source is no longer on line. If you are the original source and would like this post removed please contact us and we will take this post down immediately)<\/p>\n

        Share this:<\/h3>