开发者

Serving XHTML as application/xhtml+xml with Ruby on Rails

I'm trying to get my Rails app to serve XHTML content properly, with the correct content-type of application/xhtml+xml. Ideally with content negotiation so that IE users get a chance to use the site too.

Given that all the HTML generated by Rails is marked at XHTML 1.0 Transitional, I'm a bit surprised that there is no obvious option to make Rails serve markup as XHTML. I found this http://blog.codahale.com/2006/05/23/rails-plugin-xhtml_content_type/, but it seems to be for 1.1.2 and I can't get it 开发者_如何学Goworking properly under 2.3.8.

Have I missed something here?


Ok, I've got something that works now. Thanks to @danivovich for starting me in the right place. The first thing I had to do was sort out the Mime types in mime_types.rb so that HTML wasn't aliased with XHTML:

module Mime
  remove_const('HTML') # remove this so that we can re-register the types
end

Mime::Type.register "text/html", :html
Mime::Type.register "application/xhtml+xml", :xhtml

The I just added this to my application controller:

  before_filter :negotiate_xhtml
  after_filter :set_content_type

  def negotiate_xhtml
    @serving_polyglot = false
    if params[:format].nil? or request.format == :html
      @serving_polyglot = ((not request.accepts.include? :xhtml) or params[:format] == 'html')
      request.format = :xhtml
    end
  end

  def set_content_type
    if @serving_polyglot
      response.content_type = 'text/html'
    end
  end    

This makes sure that XHTML is always servered as such, unless the client doesn't accept it, or HTML has been explicitly requested. HTML is always just XHTML served as a polyglot. The @serving_polyglot variable is available in the views where any switching is needed.

This is working for me under Chrome, Safari, Firefox, Opera and IE[6-8].


You can force the content type in any controller function or using an after filter. Either of these methods can set the content type via:

response.content_type = "application/xhtml+xml"


Add this to your application_controller.rb:

 def correct_safari_and_ie_accept_headers
    ajax_request_types = [ 'text/javascript', 'application/json', 'text/xml']
    request.accepts.sort!{ |x, y| ajax_request_types.include?(y.to_s) ? 1 : -1 } if request.xhr?
 end

This corrects the safari and ie accept headers so that it defaults to text/xml instead of text/html. It works for me. Tested both on IE and Safari. Other browsers default to text/xml anyways.

EDIT: I have set my DOCTYPE to <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> and not XHTML Transitional.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜