IE9 отказывается обрабатывать XML-ответ

Это вопрос в отношении этого.

В UPDATE II я добавил script на основе обратной связи Jamie.

UPDATE - tl; dr:

Я создал скрипку с временным ключом, чтобы вы, ребята, могли легче видеть проблему: http://jsfiddle.net/S6wEN/.

По мере того, как этот вопрос становился слишком длинным, это резюме.

  • Я попытался использовать imgur API для обновления изображения через XHR с перекрестным доменом.
  • Чтобы абстрагировать детали в реализации, я использую плагин JQuery Form (очевидно, он содержится в скрипке).
  • Отлично работает в Chrome, Firefox и т.д., но он не работает в IE9.
  • Ожидаемый результат - обновить изображение и получить тип изображения.

Вы все еще можете найти подробности ниже.

Спасибо

У меня есть этот HTML:

<form id="uploadForm" action="http://api.imgur.com/2/upload.xml" method="POST" enctype="multipart/form-data">
 
 File: 
 Return Type: <select id="uploadResponseType" name="mimetype">
 <option value="xml">xml</option>
 </select>
 
</form>

В принципе, у меня есть форма для загрузки изображения в imgur через кросс-домен XHR. Чтобы управлять неприятными деталями, я использую JQuery Form Plugin, который хорошо работает. Однако, когда я пытаюсь отправить изображение imgur и получить ответ xml, он не работает должным образом в IE9 (я не тестировал в IE8, но я не ожидаю отличных новостей). Он отлично работает в Chrome и Firefox. Это часть javascript:

(function() {
$('#uploadForm').ajaxForm({
 beforeSubmit: function(a,f,o) {
 o.dataType = $('#uploadResponseType')[0].value;
 $('#uploadOutput').html('Submitting...');
 },
 complete: function(data) {
 var xmlDoc = $.parseXML( data.responseText ),
 $xml = $( xmlDoc );
 $('#uploadOutput').html($xml.find('type'));
 }
 });
})();

В IE9 я получаю следующие ошибки:

SCRIPT5022: Invalid XML: null 
jquery.min.js, line 2 character 10890
XML5619: Incorrect document syntax. 
, line 1 character 1

Я также использовал пример, приведенный на странице JQuery Form Plugin, в котором используется только Javascript, но это не помогает. Очевидно, первая ошибка, относящаяся к JQuery, исчезает, но я не могу получить ожидаемые результаты (в этом случае image/jpeg в div с id="uploadOutput").

Когда я смотрю на консоль в IE9, я получаю следующее:

URL Method Result Type Received Taken Initiator Wait‎‎ Start‎‎ Request‎‎ Response‎‎ Cache read‎‎ Gap‎‎
http://api.imgur.com/2/upload.xml POST 200 application/xml 1.07 KB 7.89 s click 2808 93 5351 0 0 0

и как ответ тела:

<!--?xml version="1.0" encoding="utf-8"?-->
<upload><name><title><caption/><hash>xMCdD</hash> 
<deletehash>Nb7Pvf3zPNohmkQ</deletehash><datetime>2012-03-17 01:15:22</datetime>
<type>image/jpeg</type><animated>false</animated><width>1024</width
<height>768</height><size>208053</size><views>0</views><bandwidth>0</bandwidth></image
<links><original>http://i.imgur.com/xMCdD.jpg</original
<imgur_page>http://imgur.com/xMCdD</imgur_page>
<delete_page>http://imgur.com/delete/Nb7Pvf3zPNohmkQ</delete_page>
<small_square>http://i.imgur.com/xMCdDs.jpg</small_square>
<large_thumbnail>http://i.imgur.com/xMCdDl.jpg</large_thumbnail></links></upload>
</code>

все прекрасно, но по какой-то причине я не могу обработать эту информацию на HTML-странице. Я проверил XML, чтобы быть уверенным, что это не проблема. Это действительно, конечно.

Итак, что проблема с IE9?.

ОБНОВЛЕНИЕ:

Другой способ получить XML, который работает в Chrome и Firefox, но не в IE9:

<code>(function() {
$('#uploadForm').ajaxForm({
 dataType: "xml",
 beforeSubmit: function(a,f,o) {
 o.dataType = $('#uploadResponseType')[0].value;
 $('#uploadOutput').html('Submitting...');
 },
 success: function(data) {
 var $xml = $( data ),
 element = $($xml).find('type').text();
 alert(element);
 }
 });
})(); 
</code>

ОБНОВЛЕНИЕ 2:

<code><!DOCTYPE html>
<html>
 <body>
 <form id="uploadForm" action="http://api.imgur.com/2/upload.xml" method="POST" enctype="multipart/form-data">
 <input type="hidden" name="key" value="00ced2f13cf6435ae8faec5d498cbbfe">
 File: <input type="file" name="image">
 Return Type: <select id="uploadResponseType" name="mimetype">
 <option value="xml">xml</option>
 </select>
 <input type="submit" value="Submit 1" name="uploadSubmitter1">
 </form>
 <div id="uploadOutput"></div>
 </body>
</html>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script type="text/javascript" src="jquery.form.js"></script>
​<script>
(function() {
 var options = { 
 // target: '#output1', // target element(s) to be updated with server response 
 //beforeSubmit: showRequest, // pre-submit callback 
 success: afterSuccess, // post-submit callback 
 complete: afterCompletion,
 // other available options: 
 //url: url // override for form 'action' attribute 
 type: 'POST', // 'get' or 'post', override for form 'method' attribute 
 dataType: 'xml' // 'xml', 'script', or 'json' (expected server response type) 
 //clearForm: true // clear all form fields after successful submit 
 //resetForm: true // reset the form after successful submit 
 // $.ajax options can be used here too, for example: 
 //timeout: 3000 
 }; 
 function process_xml(xml) {
 var type = $(xml).find('type').text() ;
 return type;
 // Find other elements and add them to your document
 }
 function afterSuccess(responseText, statusText, xhr, $form) { 
 // for normal html responses, the first argument to the success callback 
 // is the XMLHttpRequest object responseText property 
 // if the ajaxForm method was passed an Options Object with the dataType 
 // property set to 'xml' then the first argument to the success callback 
 // is the XMLHttpRequest object responseXML property 
 // if the ajaxForm method was passed an Options Object with the dataType 
 // property set to 'json' then the first argument to the success callback 
 // is the json data object returned by the server 
 var $xml = process_xml(responseText);
 console.log('success: ' + $xml);
 } 
 function afterCompletion(xhr,status){
 if(status == 'parsererror'){
 xmlDoc = null;
 // Create the XML document from the responseText string
 if(window.DOMParser) {
 parser = new DOMParser();
 xml = parser.parseFromString(xhr.responseText,"text/xml");
 } else {
 // Internet Explorer
 xml = new ActiveXObject("Microsoft.XMLDOM");
 xml.async = "false";
 xml.loadXML(xhr.responseText);
 }
 }
 console.log('complete: ' + process_xml(xhr.responseText));
 }
$('#uploadForm').ajaxForm(options);
})(); 
</script>
</code>

Спасибо заранее.

4 ответа

IE, как известно, суетливый, когда дело доходит до принятия XML и анализа его. Попробуйте что-то вроде этого:

function process_xml(xml) {
 var type = $(xml).find('type').text() ;
 $('#type').html(type) ;
 // Find other elements and add them to your document
}
$(function() {
 $('#uploadForm').ajaxForm({ 
 dataType: "xml", // 'xml' passes it through the browser xml parser
 success: function(xml,status) {
 // The SUCCESS EVENT means that the xml document
 // came down from the server AND got parsed successfully
 // using the browser own xml parsing caps.
 process_xml(xml);
 // Everything goes wrong for Internet Explorer
 // when the mime-type isn't explicitly text/xml.
 // If you are missing the text/xml header
 // apparently the xml parse fails,
 // and in IE you don't get to execute this function AT ALL.
 },
 complete: function(xhr,status){
 if(status == 'parsererror'){
 xmlDoc = null;
 // Create the XML document from the responseText string
 if(window.DOMParser) {
 parser = new DOMParser();
 xml = parser.parseFromString(xhr.responseText,"text/xml");
 } else {
 // Internet Explorer
 xml = new ActiveXObject("Microsoft.XMLDOM");
 xml.async = "false";
 xml.loadXML(xhr.responseText);
 }
 process_xml(xml);
 }
 },
 error: function(xhr,status,error)
 {
 alert('ERROR: ' + status) ;
 alert(xhr.responseText) ;
 }
 });
});

Кроме того, используйте alert() для всей отладки, чтобы обеспечить обратную связь о том, какая информация передается в любое время.

ИЗМЕНИТЬ

Самое главное, чтобы ваш XML файл был "хорошо сформирован", т.е. он не должен содержать любые синтаксические ошибки. Вам необходимо запустить XML файл с помощью:

Это не так много проблем с сервером, потому что ошибки исходят из вашего браузера (т.е. Internet Explorer), потому что он считает, что XML искажен. Ошибка возникает из вашего браузера и указывает, что ваш XML некорректен. Вы можете вручную установить, какие заголовки вы хотите вернуть с помощью этих настроек $.ajax():

dataType: ($.browser.msie) ? "text" : "xml",
accepts: {
 xml: "text/xml",
 text: "text/xml"
}

Или другой способ сделать то же самое - запросить определенный заголовок:

headers: {Accept: "text/xml"},

Разница между типами контента application/xml и text/xml незначительна (она основана на каждой кодировке XML), но если вы хотите знать, что можете читать этот пост.


Я использовал этот плагин раньше. Если я напомню это право, он использует iframe для извлечения информации, а затем читает содержимое в iframe. Содержимое сохраняется в файле responseText. Но IE может иметь более строгие правила, чем другие браузеры. Вы пробовали распечатать значение data.responseText?

Если значение не является строкой XML. Я ненавижу говорить об этом, но API не создан для Javascript. Я узнал, что JSONP с манипулированием тегами script - лучший способ сделать кросс-домен XHR. Который я не думаю, что этот плагин делает.


js код:

$(function() {
 $('#uploadForm').ajaxForm({
 dataType : 'xml', // OR $('#uploadResponseType option:selected').val()
 beforeSubmit : function(a, f, o) {
 $('#uploadOutput').html('Submitting...');
 },
 success : function(data) {
 var original = $(data).find('links').find('original').text();
 $('#uploadOutput').html('');
 }
 });
 });

php код:

<!--?
 $api_key = "****************************";
 $file = getcwd() . '/' . basename( $_FILES['image']['name'] );
 move_uploaded_file($_FILES['image']['tmp_name'], $file);
 $handle = fopen($file, "r");
 $data = fread($handle, filesize($file));
 $pvars = array('image' =--> base64_encode($data), 'key' => $api_key);
 $post = http_build_query($pvars);
 $curl = curl_init();
 curl_setopt($curl, CURLOPT_URL, 'http://api.imgur.com/2/upload.xml');
 curl_setopt($curl, CURLOPT_TIMEOUT, 30);
 curl_setopt($curl, CURLOPT_POST, 1);
 curl_setopt($curl, CURLOPT_POSTFIELDS, $post);
 curl_setopt($curl, CURLOPT_HTTPHEADER, array("Content-type: application/x-www-form-urlencoded"));
 curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
 $xml = curl_exec($curl); 
 curl_close ($curl);
 unlink($file);
 header('Content-type: text/xml'); 
 echo $xml;
?>


Возможно, попробуйте? Я использую это с локатором хранилища карт Google. Я замечаю, что $.parseXML на самом деле делает это внутренне, но его внутри try/catch, и его утверждение, что ваш data является нулевым (что странно?)

var xml;
 if (typeof data == "string") {
 xml = new ActiveXObject("Microsoft.XMLDOM");
 xml.async = false;
 xml.loadXML(data);
 } else {
 xml = data;
 }

Из jQuery:

// Cross-browser xml parsing
parseXML: function( data ) {
 var xml, tmp;
 try {
 if ( window.DOMParser ) { // Standard
 tmp = new DOMParser();
 xml = tmp.parseFromString( data , "text/xml" );
 } else { // IE
 xml = new ActiveXObject( "Microsoft.XMLDOM" );
 xml.async = "false";
 xml.loadXML( data );
 }
 } catch( e ) {
 xml = undefined;
 }
 if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) {
 jQuery.error( "Invalid XML: " + data );
 }
 return xml;
},

licensed under cc by-sa 3.0 with attribution.