s c h e m a t i c s : c o o k b o o k

/ Cookbook.WebIncludingDocType

This Web


WebHome 
WebChanges 
TOC (with recipes)
NewRecipe 
WebTopicList 
WebStatistics 

Other Webs


Chicken
Cookbook
Erlang
Know
Main
Plugins
Sandbox
Scm
TWiki  

Schematics


Schematics Home
Sourceforge Page
SchemeWiki.org
Original Cookbook
RSS

Scheme Links


Schemers.org
Scheme FAQ
R5RS
SRFIs
Scheme Cross Reference
PLT Scheme SISC
Scheme48 SCM
MIT Scheme scsh
JScheme Kawa
Chicken Guile
Bigloo Tiny
Gambit LispMe
GaucheChez

Lambda the Ultimate
TWiki.org

Including A DOCTYPE Declaration With A Servlet Response

Problem

You want to include a DOCTYPE declaration in your servlet response, whilst retaining the ease-of-use of the X-expression format.

Solution

The following function takes an X-expression and returns a servlet response that contains the response and the XHTML transitional DOCTYPE.

;; make-xhtml-response : xexpr -> (list-of string)
(define (make-xhtml-response xexpr)
  (list "text/html"
        "<!DOCTYPE html
           PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"
           \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">"
        (xexpr->string xexpr)))

Discussion

A servlet can return three different types of responses:

The code above uses the second method to prepend the XHTML Transitional DOCTYPE declaration to an X-expression response. The response is given the text/html MIME type. This is not recommended by the W3C, but Internet Explorer is not standards compliant and fails to correctly process file with the recommended MIME type.

The documentation for X-expressions says they represent the "interesting" part of an XML document. This is true if you aren't interested in XML standards, but the increasing use of XML on the web means that applications have to be aware of the additional requirements of XML. In particular Internet Explorer 6 reverts to the broken Internet Explorer 5 rendering model if HTML documents don't have a DOCTYPE (FireFox? of course does the right thing).

The XML library can represent a DOCTYPE, though the X-expression format cannot. To add a DOCTYPE to an X-expression by converting it to the structure representation defined in the XML library you could use the following function:

;; xexpr->xhtml : x-expression -> document
;;
;; Convert an X-expression to an XML document representing XHTML
(define (xexpr->xhtml xexpr)
  (make-document
    (make-prolog '()
                 (make-document-type
                  'html
                  (make-external-dtd/public
                   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
                   "-//W3C//DTD XHTML 1.0 Transitional//EN")
                  #f))
    (xexpr->xml xexpr)))


Comments about this recipe

The thing is, if you're going to use XHTML, you're probably going to need fine control over the HTTP headers as well. According to the W3C, there are strict requirements about the MIME type reported by the web browser for XHTML. The proper MIME type is application/xhtml+xml, but unfortunately not all browsers support this MIME type. The solution is to take a look at the "Accept" header of the request and see if the browser supports it, and otherwise use text/html.

(require (lib "servlet.ss" "web-server")
         (lib "response.ss" "web-server")
         (lib "etc.ss")
         (lib "string.ss")
         (lib "xml.ss" "xml"))

(define (accepted-mime-types request)
  (with-handlers ([exn? (lambda (exn) null)])
    (let ([header (extract-binding/single 'accept (request-headers request))])
      (regexp-split #rx",[ \t\r\n]*"
                    (if (bytes? header)
                        (bytes->string/latin-1 header)
                        header)))))

(define (xhtml-mime-type request)
  (if (and request (member "application/xhtml+xml" (accepted-mime-types request)))
      #"application/xhtml+xml"
      #"text/html"))

(define doctype
  (string-append "<!DOCTYPE html "
                 "PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" "
                 "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"))

(define make-response/xhtml
  (opt-lambda (xexpr [request #f])
    (make-response/full
     200
     "Okay"
     (current-seconds)
     (xhtml-mime-type request)
     null
     (list doctype (xexpr->string xexpr)))))

I should probably make this into a PLaneT package.

See also:

-- DaveHerman - 30 Sep 2005

Okay, I've added a new PLaneT package for this. Use:

(require (planet "xhtml.ss" ("dherman" "xhtml.plt" 1 1)))

-- DaveHerman - 30 Sep 2005

Contributors

-- NoelWelsh - 22 Nov 2004

CookbookForm
TopicType: Recipe
ParentTopic: WebRecipes
TopicOrder: 999

 
 
Copyright © 2004 by the contributing authors. All material on the Schematics Cookbook web site is the property of the contributing authors.
The copyright for certain compilations of material taken from this website is held by the SchematicsEditorsGroup - see ContributorAgreement & LGPL.
Other than such compilations, this material can be redistributed and/or modified under the terms of the GNU Lesser General Public License (LGPL), version 2.1, as published by the Free Software Foundation.
Ideas, requests, problems regarding Schematics Cookbook? Send feedback.
/ You are Main.guest