これ僕.com:行動分析学マニアがおくる行動戦略

意図と行動のギャップから生じる「不自由さ」への挑戦。果たして僕たちに自由はあるのか?

Rails2.0とXHTMLとXMLHttpRquest.responseXML

Railsで色々処理して結果をXHTMLで返すアプリを作ったのです。で、使い勝手とかあんまり意識してないので、jQueryを使ってUI部分を1階層ラップしたい。具体的には、jQuery.ajax()のXMLHttpRequest.responseXMLでレンダリングされたXHTMLを受け取ってぐりぐり弄りたい、と。
が、responseXMLがどうもnullってるのです。Operaだとnullってない。MacのFirefoxSafariはnullってる。

調べた結果、Content-Typeがtext/hmtlだと普通はresponseXMLにいれないらしい。Operaが特殊らしい。っていうか、このケースだとContent-Typeを無視してやがるっぽい。で、どうやらtext/xmlとかapplication/xmlを返せばどうにかなるっぽいことが分かる。


ああ、respond_toのformat.xmlを使えばいけそうね、と思う。が、わざわざhoge.xml.erbを作るのはいやだ。っていうか、結果自体はいま作ってあるXHTMLレンダリングされたものが欲しいのだよ。

で、こうしてみた。

respond_to do |format|
  format.html
  format.xml  { render :template => "foos/bar.html.erb", :layout => "foos.html.erb" }
end

これならContent-Typeがapplication/xmlになってresponseXMLで受け取れるみたい。↓みたいなことができた。

jQuery.ajax({
  type: "GET",
  url...
  ...
  complete: function(xmlHttpReq) {
    $("#hoge", xmlHttpReq.responseXML).appendTo("#output");
  }
});


・・・と思ったらInternet Explorerで動かねぇ。くそぅ。


追記。

IEのXMLHttpRequestオブジェクトのresponseXMLプロパティの値は、Content-Typeが"text/xml"ではない場合にはnullになります。

という記述を見つける。んー・・・app/controller/application.rbにFilterを追加してみる。

after_filter :set_content_type

def set_content_type
  if request.user_agent.include? "MSIE"
    unless headers["Content-Type"].nil?
      headers["Content-Type"] = "text/xml; charset=utf-8" if headers["Content-Type"].include? "application/xml"
    end
  end
end

で、jQuery

alert(xmlHttpReq.getResponseHeader("Content-Type"));

ってやると"text/xml; charset=utf-8"と表示されるのだけど、相変わらずresponseXMLはダメっぽ。responseTextにはちゃんと入ってきてるんだけどなぁ。
症状的にはresponseXMLでのXMLデータ取得 − Java Solution − @ITと同じっぽいが。


追記2
jQueryprototype.jsに変更しても、症状は同じ。XHTMLがおかしいのかな。。。


追記3
[JavaScript]responseXMLではまった / LiosK-free Blog
こちらのサイトがresponseXMLの扱いについてよく纏まっていて助かりました。結局の所、結論は「つかえねぇw」ですが。orz
responseTextで頑張るか、json化するか。いっそのことFlash・・・。