2012-04-09 10 views
20

Come dovrei aggirare il problema tra domini quando analizzo XML da un server/dominio diverso? Qualcuno potrebbe fornirmi un esempio? L'esempio non deve essere limitato a solo jQuery, poiché anche JavaScript sarà sufficiente.Come analizzare il dominio incrociato XML in jQuery?

+0

cosa intendi per crossdomain –

+1

Solo l'esecuzione tra domini consentita da JavaScript è JSONP. – AlienWebguy

+0

"Le richieste di script e JSONP non sono soggette alle stesse restrizioni sui criteri di origine." –

risposta

66

Per comprendere completamente il motivo per cui lo puro XML interdominio non funzionerà, è utile esaminare innanzitutto come è facilitato il JSON interdominio.

In primo luogo, diamo un'occhiata a ciò che accade quando si effettua una richiesta AJAX in jQuery:

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

Nell'esempio precedente, la richiesta AJAX è fatto relativo al dominio. Sappiamo che se tentiamo di aggiungere un dominio diverso prima del percorso, la richiesta non riuscirà con un'eccezione di sicurezza.

Tuttavia, ciò non vuol dire che il browser non possa effettuare richieste a un altro dominio. Ecco un esempio che può essere familiare a voi:

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

In base alla nostra conoscenza di come importare JavaScript nella pagina, si vede che è possibile caricare una risorsa che esiste su un altro dominio!

JSONP è un concetto che sfrutta questa conoscenza. JSONP sta per "JSON with padding", e il suo successo dipende dal fatto che gli oggetti JavaScript possono essere espressi usando una notazione stringa e il fatto che i tag script JavaScript possono caricare ed eseguire contenuti da domini esterni.

Sotto il cofano, JSONP di jQuery sembra qualcosa di simile anche se può non essere precisi:

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

Inoltre, sulla pagina da qualche parte, si definisce un gestore di callback:

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

Qui, facciamo la richiesta:

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

Per far funzionare correttamente questo, il nostro script PHP deve entrambi restituiscono i dati in formato JSON e devono anche aggiungere "padding" attorno alla stringa sotto forma di un nome di funzione JavaScript che potremmo passare come parametro (ad es. "Callback")

Quindi, la risposta del server può essere simile a questo, se dovessimo guardare nella scheda NET Firebug o Chrome:

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

Perché sappiamo contenuto JavaScript viene eseguito come Appena scaricato, la nostra funzione processData definita in precedenza viene immediatamente richiamata e viene passata come parametro alla nostra stringa JSON. Viene quindi avvisato utilizzando JSON.stringify per riconvertire l'oggetto in una stringa.

Poiché si tratta di un oggetto, ho potuto accedere anche le sue proprietà, in questo modo:

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

Infine, passiamo alla domanda principale: Può JSONP essere usato per ottenere l'XML, o possiamo analizzare croce XML -dominio? La risposta, come altri hanno fatto notare, è un sonoro NO, ma diamo un'occhiata al motivo per cui utilizzando un esempio:

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

Ora, che cosa accadrà se XML grezzo viene passato alla funzione? Si romperà, poiché JavaScript non ha modo di convertire XML in JSON.

Tuttavia, supponiamo abbiamo messo l'XML tra virgolette:

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

Ora, in questo esempio, la variabile JsonResult ha effettivamente una stringa, che siamo in grado di lavorare. Usando alcune utilità di analisi XML JavaScript, potremmo caricare quella stringa nel parser DOM XML e fare cose con esso!

Tuttavia, non è puro XML, è ancora una risposta JavaScript sotto il cofano. Il tipo di risposta dal server PHP è ancora text/javascript, e stiamo ancora usando un tag script per caricare quello che è veramente solo JavaScript.

In sintesi, potresti lavorare con "XMLP" o XML con padding (l'ho appena inventato, non è reale!), Ma se hai intenzione di passare attraverso tutti i problemi di modificare effettivamente la tua risposta a restituisci una funzione callback wrapper, puoi anche convertire l'output in JSON e lasciare che il browser gestisca le conversioni automaticamente e in modo nativo e risparmia la fatica di dover utilizzare un parser XML.

Ma se per qualche motivo è più semplice conservare i dati in formato XML, è possibile modificare la risposta e assegnargli un wrapper JavaScript.

I casi in cui potrei vedere questo essere utile potrebbe essere se si dispone di dati XML da un'applicazione legacy archiviati in un database e si restituisce al lato client tramite remoting script-tag o chiamate JSONP.

+8

è molto utile, +1. ti meriti i complimenti – defau1t

4

Ho trovato un'ottima soluzione per recuperare xml dalla richiesta di ajax su più domini.

Poiché jQuery 1.5 è possibile utilizzare dataType "jsonp xml" (http://api.jquery.com/jQuery.ajax/)!

così ho usato questo: lato

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

Server per i miei Webservices ho usato per incapsulare il risultato stringa XML all'interno del callback creato da 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); 
     } 

e il metodo magico (ho trovato in un altro thread Stack) che dovrai disinfettare la tua stringa xml (quindi javascript può analizzarlo):

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

Spero che questo aiuti!

+9

Ho ricevuto un errore 'Uncaught SyntaxError: Unexpected token <' quando ho provato questo, ad esempio:' $ .get ('http://www.webservicex.net/geoipservice.asmx/GetGeoIPContext', funzione (dati) {console.log (dati);}, 'jsonp xml'); ' – 10basetom

+2

Questo è utile solo quando si ha accesso al codice del server. –

Problemi correlati