Подтвердить что ты не робот

Как обрабатывать XML-кросс-домен в jQuery?

Как мне обойти проблему между доменами при анализе XML с другого сервера/домена? Может ли кто-нибудь предоставить мне пример? Пример не должен ограничиваться только jQuery, так как JavaScript также будет достаточным.

4b9b3361

Ответ 1

Чтобы полностью понять, почему чистый междоменный XML не будет работать, он помогает сначала посмотреть, как облегчается междоменный JSON.

Во-первых, давайте посмотрим, что произойдет, когда вы выполните запрос AJAX в jQuery:

$.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 означает "JSON with padding", и успех этого успеха зависит от того, что объекты JavaScript могут быть выражены с использованием строковой нотации, а также то, что теги JavaScript script могут загружать и запускать контент из внешних доменов.

Под капотом 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 script должен как вернуть данные в формате JSON, так и добавить "дополнение" вокруг строки в виде имени функции JavaScript, которое мы можем передать в качестве параметра (т.е. "обратный вызов" )

Таким образом, ответ с сервера может выглядеть примерно так, если бы мы посмотрели его на вкладке Firebug или Chrome NET:

processData( { "userId" : "123" , "name" : "James" , "email" : "[email protected]" } );

Поскольку мы знаем, что содержимое 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-домен? Ответ, как указывали другие, - это громкое НЕТ, но давайте посмотрим, почему, используя пример:

processData(<?xml version="1.0"><user><userid>12345</userid><name>James</name><email>[email protected]</email></user>);

Теперь, что произойдет, если исходный XML будет передан в функцию? Он сломается, поскольку JavaScript не имеет возможности преобразовать XML в JSON.

Однако предположим, что мы помещаем XML в кавычки:

processData("<?xml version="1.0"><user><userid>12345</userid><name>James</name><email>[email protected]</email></user>");

Теперь в этом примере переменная jsonResult фактически принимает строку, с которой мы можем работать. Используя некоторые утилиты для анализа XML JavaScript, мы могли бы загрузить эту строку в XML DOM Parser и делать с ней все!

Однако, это не чистый XML, это еще ответ JavaScript под капотом. Тип ответа с сервера PHP по-прежнему является текстовым /javascript, и мы все еще используем тег script для загрузки того, что на самом деле является просто обычным JavaScript.

В общем, вы можете работать с XMLP или XML с дополнением (я только что сделал это, это не реально!), но если вы собираетесь решить все проблемы, связанные с фактическим изменением вашего ответа на возврат вы можете просто преобразовать свой вывод в JSON и позволить браузеру обрабатывать преобразования автоматически и изначально и избавить себя от необходимости использовать XML-парсер.

Но если по какой-то причине проще хранить данные в формате XML, вы можете изменить ответ и дать ему оболочку JavaScript.

Случаи, когда я мог бы заметить, что это полезно, могут быть, если у вас есть данные XML из устаревшего приложения, хранящиеся в базе данных, и вы возвращаете его на стороне клиента, используя script -tag remoting или JSONP-вызовы.

Ответ 2

Я нашел очень хорошее решение для извлечения xml из запроса ajax междоменной области.

Так как 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 }
        });

На стороне сервера для моих веб-служб я использовал для инкапсуляции результата строки xml в обратном вызове, созданном jQuery:

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();
        }

Надеюсь, это поможет!