IE7 の XMLHttpRequest と responseXML の謎

観測気球

収集物の記録書庫 a data archive of collection -- collectible toys

[要旨] responseText は問題なく使えるのに、なぜか responseXML を使おうとすると問題が発生します。
[キーワード] Internet Explorer,Firefox,FireBug

« コナカ(BlogPet) | トップページ | Mash up Award 2nd 審査結果発表 »

2007.03.21

IE7 の XMLHttpRequest と responseXML の謎

XMLHttpRequest を利用する JavaScript (を含む html) を Web サーバ上に置いて、ブラウザからアクセスする分には、IE7 も Firefox 2.x も Opera 9.x も同じような動作をする*1んだけど、全く同じ内容の「JavaScript (を含む html)」をローカルPCに置いたときは挙動が違います。

*1
厳密には、open する URL が同一サーバ内か別サーバかで挙動が違います。同一サーバ内は、IE7 も Firefox 2.x も Opera 9.x も問題なくアクセス可能、別サーバの場合は、IE7 のみ「セキュリティ上の危険があるけど、本当にアクセスしてもいいの?」(ちょっと意訳)みたいなダイアログが出て、「いいよ」と答えるとアクセスできてしまいます。こういう仕様でいいのかなぁ。

ローカルPC上に置いた html ファイル内から JavaScript の XMLHttpRequest を使う場合の挙動の違い

IE6 までは、XMLHttpRequest 相当のことをやろうとすると ActiveXObject("Msxml2.XMLHTTP") か ActiveXObject("Microsoft.XMLHTTP") を使うしか手はなかったんですが、IE7 からはこの方法以外にそのものずばり XMLHttpRequest を使うこともできるようになりました。つまり、両方使えるわけですが、なぜか、ローカルPC に置いた html から使う場合は、挙動が違うんですよね。

IE7 で ActiveXObject("Msxml2.XMLHTTP") を使う場合

responseText は問題なく使える(ローカルPC上にあるテキストファイルを読み出せる)のに、responseXML で XML ファイルを読んでも、中身が空になってしまいます。XML ファイルを responseText で読むと、ちゃんと読めるのに。これは仕様? それともバグ?

で、この XML ファイルを Web サーバ上に置いた(ただし、html + JavaScript 自体はローカルPCに置いたまま)場合は、responseXML でちゃんと XML ファイルの中身が読める。なので、XML ファイルの中身に問題があるとか、そういうことではありません。純粋に XML ファイルの置き場所の違いだけで挙動に違いが発生するという話。

IE7 で XMLHttpRequest を使う場合

なぜか open しようとした時点で「アクセスが拒否されました」というエラーダイアログが表示されます。セキュリティ上の理由か何かで、ローカルPC上のファイルへのアクセスは禁止してるのかな? XML ファイルを Webサーバ上に置くと、問題なくアクセスできるし、responseXML によるファイルの中身の取得もできます。

Firefox の responseXML

ちなみに、Firefox 2 でもちょっと不思議な挙動を観測。FireBug が入ってるかいないかで挙動が違うんですよね。 ローカルファイルに対する responseText は FireBug の有無関係なしにちゃんと動く。一方、responseXML は、FireBug が入ってない時は中身が空、FireBug が入っているときはちゃんと中身が取れる。FireBug を入れると、Firefox の XMLHttpRequest 回りの挙動が変わるなんて、聞いてないよ。

[2007年3月22日追記]

FireBug が入ってない状態でも、prototype.js の Ajax.Request を使った場合は、responseXML の中身、ちゃんと入りますね。prototype.js が何かごにょごにょしてるんだろうなぁ。ソースを確認してみないと。

一方、IE の場合は、prototype.js の Ajax.Request を使っても症状が変わりませんでした(IE7 だけじゃなくて、IE6 も同様の症状が発生することを確認)。MIME type の設定(レジストリ)を確認してみたら、ちゃんと text/xml になってました。なので、MIME type の設定を変えたら直るのでは? という解決策は×です。

[追記、ここまで]

検証用のコード

参考までに、JavaScript を含む html ソースを、以下に示します。

hello.html
<html>
<head>
<meta http-equiv="Content-type" CONTENT="text/html; charset=UTF-8">
<meta http-equiv="Content-script-type" CONTENT="text/javascript">
<title>XMLHttpRequest回りの挙動の違いをチェックする</title>
<script type="text/javascript">

function createHttpRequest(type) {
    if ( type == 1 ) {
        if( window.XMLHttpRequest )
            return new XMLHttpRequest();
        if ( window.ActiveXObject ) {
            try {
                return new ActiveXObject("Msxml2.XMLHTTP");
            } catch (e) {
                try {
                    return new ActiveXObject("Microsoft.XMLHTTP");
                } catch (e2) {}
             }
        }
    }
    else {
        if ( window.ActiveXObject ) {
            try {
                return new ActiveXObject("Msxml2.XMLHTTP");
            } catch (e) {
                try {
                    return new ActiveXObject("Microsoft.XMLHTTP");
                } catch (e2) {}
             }
        }
        else if( window.XMLHttpRequest )
            return new XMLHttpRequest();
    }

    return null;
}

function getFile(data, method, fileName, async, target, type) {
    var request = createHttpRequest(type);

    request.open(method, fileName, async);

    request.onreadystatechange = function() {
        if ( request.readyState == 4 ) {
            onLoaded(request, target);
        }
    }

    request.send( data );
}

function onLoaded(request, target) {
    if ( target == 1 ) {
        var res = request.responseText;

        var w = document.getElementById("result");
        w.innerHTML = res;
    }
    else {
        var res = request.responseXML;

        var w = document.getElementById("result");
        w.innerHTML = res.getElementsByTagName("message")[0].firstChild.nodeValue;
    }
}

function run(target,location,type) {
    var url = location == 1 ? "./" : "http://localhost:8080/test/";
    url += target == 1 ? "hello.txt" : "hello.xml";

    getFile("", "GET", url, false, target, type);
}

function clear() {
    var w = document.getElementById("result");
    w.innerHTML = "";
}
</script>
</head>

<body>
<form id="form111" action="javascript:run(1,1,1)" method="get">
<input type="submit" value="XMLHttpRequest,ローカルtxt 実行">
</form>
<form id="form112" action="javascript:run(1,1,2)" method="get">
<input type="submit" value="Msxml2.XMLHTTP,ローカルtxt 実行">
</form>

<form id="form121" action="javascript:run(1,2,1)" method="get">
<input type="submit" value="XMLHttpRequest,リモートtxt 実行">
</form>
<form id="form122" action="javascript:run(1,2,2)" method="get">
<input type="submit" value="Msxml2.XMLHTTP,リモートtxt 実行">
</form>

<form id="form211" action="javascript:run(2,1,1)" method="get">
<input type="submit" value="XMLHttpRequest,ローカルxml 実行">
</form>
<form id="form212" action="javascript:run(2,1,2)" method="get">
<input type="submit" value="Msxml2.XMLHTTP,ローカルxml 実行">
</form>

<form id="form221" action="javascript:run(2,2,1)" method="get">
<input type="submit" value="XMLHttpRequest,リモートxml 実行">
</form>
<form id="form222" action="javascript:run(2,2,2)" method="get">
<input type="submit" value="Msxml2.XMLHTTP,リモートxml 実行">
</form>

<div id="result"></div>

<form id="form999" action="javascript:clear()" method="get">
<input type="submit" value="消去">
</form>

</body>
</html>
hello.txt
こんにちはこんにちは!!
hello.xml
<?xml version="1.0" encoding="UTF-8"?>
<message>
こんにちはこんにちは!!
</message>

responseXML で取得したはずの XML から中身を抜き出そうとするところでエラーが発生
responseXML の中身が空のときに発生するエラーをデバッガで解析している様子

投稿者: tsupo 2007.03.21 午後 11:22 | 固定リンク | このエントリーをはてなブックマークに追加 | このエントリを del.icio.us に登録 このエントリの del.icio.us での登録状況 | このエントリを Buzzurl に追加このエントリの Buzzurl での登録状況 | このエントリをlivedoorクリップに登録 このエントリのlivedoorクリップでの登録状況 このエントリをlivedoorクリップに登録している人の数 | 酢鶏巡回中

楽天市場


プログラミング」カテゴリ内の最近の記事

品揃え豊富で安い!NTT-X Store


アマゾンわくわく探検隊

トラックバック

この記事のトラックバックURL:
http://app.cocolog-nifty.com/t/trackback/6737/14342306

この記事へのトラックバック一覧です: IE7 の XMLHttpRequest と responseXML の謎:

コメント


ieは隠しセキュリティゾーンとしてマイコンピュータをもってますよ
昔から

投稿者: test (2008.07.08 午前 04:35)

コメントを書く




※イタズラ防止のため、メールアドレスを入力しないと投稿できません。

次からのコメント入力の手間を省くために、名前やメールアドレスをcookieに記憶しますか?


URL を入力すると、その URL にリンクがはられます。
なお、メールアドレスは公開されません。ご安心ください。


ワード

ニッセン

fujisan.co.jp

楽天市場