Cómo analizar XML entre dominios en jQuery?

¿Cómo solucionaría el problema de dominios cruzados al analizar XML desde un servidor / dominio diferente? ¿Podría alguien darme un ejemplo? El ejemplo no tiene que estar restringido solo a jQuery, ya que JavaScript también será suficiente.

Para comprender completamente por qué el XML puro de dominios cruzados no funcionará, primero ayuda a ver cómo se facilita el dominio cruzado de JSON.

Primero, veamos qué sucede cuando haces una solicitud de AJAX en jQuery:

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

En el ejemplo anterior, la solicitud AJAX se realiza en relación con el dominio. Sabemos que si intentamos agregar un dominio diferente antes de la ruta, la solicitud fallará con una excepción de seguridad.

Sin embargo, eso no significa que el navegador no pueda realizar solicitudes a otro dominio. Aquí hay un ejemplo que puede serle familiar:

  

Según nuestro conocimiento de cómo importar JavaScript en la página, vemos que es posible cargar un recurso que existe en otro dominio.

JSONP es un concepto que explota este conocimiento. JSONP significa “JSON con relleno”, y su éxito depende del hecho de que los Objetos JavaScript se puedan express usando una notación de cadena, y el hecho de que las tags JavaScript pueden cargar y ejecutar contenido desde dominios externos.

Debajo del capó, el JSONP de jQuery parece algo así aunque puede no ser exacto:

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

Además, en la página en algún lugar, definimos un manejador de callback:

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

Aquí, hacemos la solicitud:

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

Para que esto funcione correctamente, nuestra secuencia de comandos PHP debe devolver los datos en formato JSON, y también debe agregar “relleno” alrededor de la cadena en forma de un nombre de función de JavaScript que podemos pasar como un parámetro (es decir, “callback”) )

Por lo tanto, la respuesta del servidor puede parecerse a esto, si tuviéramos que verlo en la pestaña Firebug o Chrome NET:

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

Como sabemos que el contenido de JavaScript se ejecuta tan pronto como se descarga, nuestra función processData que definimos anteriormente se llama inmediatamente y se pasa nuestra cadena JSON como parámetro. Luego se alerta, usando JSON.stringify para convertir el objeto nuevamente en una cadena.

Como es un objeto, también pude acceder a sus propiedades, así:

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

Finalmente, pasemos a la pregunta principal: ¿se puede usar JSONP para obtener XML, o podemos analizar XML entre dominios? La respuesta, como han señalado otros, es un NO rotundo, pero veamos por qué al usar un ejemplo:

 processData(12345Jamesexample@example.com); 

Ahora, ¿qué pasará si se pasa XML sin formato a la función? Se romperá, ya que JavaScript no tiene forma de convertir XML en JSON.

Sin embargo, supongamos que ponemos el XML entre comillas:

 processData("12345Jamesexample@example.com"); 

Ahora, en este ejemplo, la variable jsonResult realmente toma una cadena, con la que podemos trabajar. Utilizando algunas utilidades de análisis XML de JavaScript, podríamos cargar esa cadena en el Analizador DOM de XML y ¡hacer cosas con eso!

Sin embargo, no es XML puro, sigue siendo una respuesta de JavaScript bajo el capó. El tipo de respuesta del servidor PHP sigue siendo texto / javascript, y todavía estamos usando una etiqueta de script para cargar lo que realmente es simplemente JavaScript.

En resumen, podrías trabajar con “XMLP” o XML con relleno (¡ya lo inventé, no es real!), Pero si vas a pasar por todo el trabajo de modificar tu respuesta para devolver una función de callback envoltorio, también puede simplemente convertir su salida a JSON y dejar que el navegador maneje las conversiones de forma automática y nativa y se ahorrará la molestia de tener que usar un analizador XML.

Pero si por alguna razón es más fácil mantener sus datos en formato XML, podría modificar la respuesta y darle un contenedor de JavaScript.

Los casos en los que podría ver que esto es útil podrían serlo si tiene datos XML de una aplicación heredada almacenada en una base de datos, y los devuelve al lado del cliente usando la comunicación remota mediante script-script o las llamadas JSONP.

Encontré una muy buena solución para recuperar xml de la solicitud ajax de dominios cruzados.

Desde jQuery 1.5 puedes usar dataType “jsonp xml” (http://api.jquery.com/jQuery.ajax/).

Entonces usé esto:

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

La parte del servidor para mis servicios web solía encapsular el resultado de la cadena xml dentro de la callback creada por 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); } 

y el método mágico (lo encontré en otro subproceso de Stack) que necesitará desinfectar su cadena xml (para que javascript pueda analizarlo):

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

Espero que esto ayude!

Me doy cuenta de que esta es una vieja pregunta, pero encontré esto mientras buscaba. Y también, creo que la respuesta es para una pregunta ligeramente diferente a la que se publicó aquí, así que quiero agregar esta respuesta que debería funcionar al menos en jQuery 1.12 y posteriores. No he probado en versiones anteriores.

De acuerdo, quiero solicitar esta URL: http://sample.domain/feeds/itemdata.xml

Y quiero encontrar el Item que se parece a esto:

  1228101530 ...  

Esto funciona, entre dominios:

 $.ajax({ dataType: "xml", url: "http://sample.domain/feeds/itemdata.xml", success: function(xml) { var itemdata = $(xml).find("ProductItemNo:contains('1228101530')").parent(); } });