21

別のサーバー/ドメインからXMLを解析するときに、クロスドメインの問題を回避するにはどうすればよいですか?誰かが私に例を教えてもらえますか?JavaScriptでも十分なので、例をjQueryのみに制限する必要はありません。

4

3 に答える 3

68

純粋なクロスドメインXMLが機能しない理由を完全に理解するには、最初にクロスドメインJSONがどのように促進されるかを確認することが役立ちます。

まず、jQueryでAJAXリクエストを行うとどうなるか見てみましょう。

$.ajax({
    url: '/user.php?userId=123',
    success: function(data) {
        alert(data); // alerts the response
    });

上記の例では、AJAXリクエストはドメインに関連して行われます。パスの前に別のドメインを追加しようとすると、セキュリティ例外が発生してリクエストが失敗することがわかっています。

ただし、ブラウザが別のドメインにリクエストを送信できないわけではありません。おなじみの例を次に示します。

<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>

ページにJavaScriptをインポートする方法に関する知識に基づいて、別のドメインに存在するリソースをロードできることがわかりました。

JSONPは、この知識を活用する概念です。JSONPは「JSONwithpadding」の略で、JavaScriptオブジェクトを文字列表記を使用して表現できることと、JavaScriptスクリプトタグが外部ドメインからコンテンツを読み込んで実行できることにかかっています。

内部的には、jQueryのJSONPは正確ではないかもしれませんが、次のようになります。

// programmatically load a script tag on the page using the given url
function loadRemoteData(url) {
    var script = document.createElement("script");
    script.setAttribute("type","text/javascript");
    script.setAttribute("src", url);
    document.getElementsByTagName("head")[0].appendChild(script);
}

また、ページのどこかに、コールバックハンドラーを定義します。

function processData(jsonResult) {
    alert(JSON.stringify(jsonResult)); //alert the JSON as a string
}

ここで、リクエストを行います。

// make a request for the data using the script tag remoting approach.
loadRemoteData("http://example.com/users.php?userId=123&callback=processData");

これが正しく機能するためには、PHPスクリプトがデータをJSON形式で返す必要があります。また、パラメーターとして渡すことができるJavaScript関数名の形式で文字列の周りに「パディング」を追加する必要があります(つまり、「コールバック」)。 )。

したがって、FirebugまたはChrome NETタブで確認すると、サーバーからの応答は次のようになります。

processData( { "userId" : "123" , "name" : "James" , "email" : "example@example.com" } );

JavaScriptコンテンツはダウンロードされるとすぐに実行されることがわかっているため、processData前に定義した関数がすぐに呼び出され、JSON文字列がパラメーターとして渡されます。次に、JSON.stringifyを使用してオブジェクトを文字列に変換し直すことで、アラートが送信されます。

これはオブジェクトなので、次のようにプロパティにアクセスすることもできます。

function processData(jsonResult) {
    alert(JSON.stringify(jsonResult)); //alert the JSON as a string

    // alert the name and email
    alert("User name is " + jsonResult.name + " and email is " + jsonResult.email);
}

最後に、主な質問に移りましょう。JSONPを使用してXMLをフェッチできますか、それともXMLクロスドメインを解析できますか? 他の人が指摘しているように、答えははっきりとNOですが、例を使用してその理由を見てみましょう。

processData(<?xml version="1.0"><user><userid>12345</userid><name>James</name><email>example@example.com</email></user>);

では、生のXMLが関数に渡されるとどうなりますか?JavaScriptにはXMLをJSONに変換する方法がないため、機能しなくなります。

ただし、XMLを引用符で囲んでいるとします。

processData("<?xml version="1.0"><user><userid>12345</userid><name>James</name><email>example@example.com</email></user>");

さて、この例では、jsonResult変数は実際に文字列を取ります。これを操作できます。いくつかのJavaScriptXML解析ユーティリティを使用して、その文字列をXML DOMパーサーにロードし、それを使って何かを行うことができます。

ただし、これは純粋なXMLではなく、内部ではJavaScriptの応答です。PHPサーバーからの応答タイプは引き続きtext/javascriptであり、スクリプトタグを使用して実際には単なるJavaScriptをロードしています。

要約すると、「XMLP」またはパディング付きのXMLで作業できます(私はそれを作りました、それは現実ではありません!)が、実際に応答を変更して関数コールバックを返すというすべての問題を経験する場合ラッパーの場合は、出力をJSONに変換し、ブラウザーに変換を自動的かつネイティブに処理させて、XMLパーサーを使用する手間を省くことができます。

ただし、何らかの理由でデータをXML形式で保持する方が簡単な場合は、応答を変更してJavaScriptラッパーを指定できます。

これが役立つと思われるのは、レガシーアプリケーションのXMLデータがデータベースに保存されていて、スクリプトタグリモーティングまたはJSONP呼び出しを使用してクライアント側に返す場合です。

于 2012-04-09T05:09:02.523 に答える
5

クロスドメインajaxリクエストからxmlを取得するための非常に優れたソリューションを見つけました。

jQuery 1.5以降、dataType "jsonp xml"(http://api.jquery.com/jQuery.ajax/)を使用できます。

だから私はこれを使用しました:

$.ajax({
            type: "GET",
            url: "http://yoururl",
            dataType: "jsonp xml",
            success: function(xmlResponse) { // process data }
        });

jQueryによって作成されたコールバック内にxml文字列の結果をカプセル化するために使用したWebサービスのサーバー側:

private static Stream GetXmlPStream(string result, string callback)
        {
            if (result == null)
                result = string.Empty;

            result = EncodeJsString(result);

            if (!String.IsNullOrEmpty(callback))
                result = callback + "(" + result + ");";

            byte[] resultBytes = Encoding.UTF8.GetBytes(result);

            if (WebOperationContext.Current != null)
                WebOperationContext.Current.OutgoingResponse.ContentType = "application/xml";
            return new MemoryStream(resultBytes);
        }

そして、xml文字列をサニタイズする必要がある魔法のメソッド(私は別のスタックスレッドで見つけました)(javascriptがそれを解析できるようにするため):

private static string EncodeJsString(string s)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("\"");
            foreach (char c in s)
            {
                switch (c)
                {
                    case '\"':
                        sb.Append("\\\"");
                        break;
                    case '\\':
                        sb.Append("\\\\");
                        break;
                    case '\b':
                        sb.Append("\\b");
                        break;
                    case '\f':
                        sb.Append("\\f");
                        break;
                    case '\n':
                        sb.Append("\\n");
                        break;
                    case '\r':
                        sb.Append("\\r");
                        break;
                    case '\t':
                        sb.Append("\\t");
                        break;
                    default:
                        int i = (int)c;
                        if (i < 32 || i > 127)
                        {
                            sb.AppendFormat("\\u{0:X04}", i);
                        }
                        else
                        {
                            sb.Append(c);
                        }
                        break;
                }
            }
            sb.Append("\"");

            return sb.ToString();
        }

これがお役に立てば幸いです。

于 2013-01-16T17:00:55.313 に答える
0

これは古い質問だと思いますが、検索中に見つけました。また、答えはここに投稿されたものとは少し異なる質問に対するものだと思うので、少なくともjQuery1.12以降で機能するはずのこの答えを追加したいと思います。以前のバージョンではテストしていません。

OK、このURLをリクエストしたい:http://sample.domain/feeds/itemdata.xml

Itemそして、私は次のように見えるを見つけたいと思います:

<Item>
  <ProductItemNo>1228101530</ProductItemNo>
  ...
</Item>

これは機能します、クロスドメイン:

$.ajax({
  dataType: "xml", 
  url: "http://sample.domain/feeds/itemdata.xml", 
  success: function(xml) {
    var itemdata = $(xml).find("ProductItemNo:contains('1228101530')").parent();
  }
});
于 2018-05-07T12:34:02.047 に答える