2012-04-09 11 views
20

Wie würde ich das domänenübergreifende Problem umgehen, wenn ich XML von einem anderen Server/einer anderen Domäne analysiere? Kann mir jemand ein Beispiel geben? Das Beispiel muss nicht nur auf jQuery beschränkt sein, da auch JavaScript ausreicht.Wie XML Cross-Domäne in jQuery zu analysieren?

+0

was meinst du mit crossdomain –

+1

Nur die von JavaScript zugelassene domainübergreifende Ausführung ist JSONP. – AlienWebguy

+0

"Skript- und JSONP-Anfragen unterliegen nicht denselben Richtlinieneinschränkungen für die Herkunft." –

Antwort

66

Um zu verstehen, warum pure Cross-Domain-XML wird nicht funktionieren, hilft es, zuerst zu sehen, wie Cross-Domain-JSON erleichtert wird.

Lassen Sie uns zuerst schauen, was passiert, wenn Sie einen AJAX-Request in jQuery machen:

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

Im obigen Beispiel ist der AJAX-Request an die Domain relativiert. Wir wissen, dass beim Versuch, eine andere Domäne vor dem Pfad hinzuzufügen, die Anforderung mit einer Sicherheitsausnahme fehlschlägt.

Das heißt jedoch nicht, dass der Browser keine Anfragen an eine andere Domain stellen kann. Hier ist ein Beispiel, die Sie vertraut ist:

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

Basierend auf unserem Wissen, wie JavaScript auf der Seite zu importieren, sehen wir, dass es möglich ist, eine Ressource zu laden, die auf einer anderen Domäne vorhanden!

JSONP ist ein Konzept, das dieses Wissen ausnutzt. JSONP steht für "JSON with padding", und sein Erfolg hängt von der Tatsache ab, dass JavaScript-Objekte mit einer String-Notation ausgedrückt werden können und dass JavaScript-Script-Tags Inhalte von externen Domains laden und ausführen können.

Unter der Haube jQuery JSONP ungefähr so ​​aussieht, obwohl es nicht genau sein kann:

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

auch irgendwo auf der Seite, definieren wir einen Callback-Handler:

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

Hier wir machen die Anfrage:

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

Für diese richtig zu arbeiten, unsere PHP-Skript muss beide geben die Daten im JSON-Format zurück und müssen außerdem "padding" um den String in Form eines JavaScript-Funktionsnamens einfügen, den wir als Parameter übergeben können (d. h. „Rückruf“)

Somit ist die Antwort vom Server in etwa so aussehen kann, wenn wir es in der Firebug oder Chrome NET Tab sehen waren:

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

Weil wir wissen, JavaScript-Inhalte werden als sobald es heruntergeladen wird, wird unsere zuvor definierte processData-Funktion sofort aufgerufen und unsere JSON-Zeichenfolge als Parameter übergeben. Es wird dann mit JSON.stringify alarmiert, um das Objekt wieder in eine Zeichenfolge umzuwandeln.

Da es sich um ein Objekt ist, könnte ich auch, dass es Eigenschaften zugreifen, etwa so:

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

Schließlich lassen Sie uns auf die Hauptfrage bewegen: Kann XML holen JSONP verwendet werden, oder können wir XML Quer analysieren -Domain? Die Antwort, wie andere haben darauf hingewiesen, ist ein klares Nein, aber schauen wir uns an, warum an einem Beispiel:

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

Nun, was passieren wird, wenn XML-Rohdaten in die Funktion übergeben wird? Es wird abgebrochen, da JavaScript keine Möglichkeit bietet, XML in JSON zu konvertieren.

jedoch an, dass wir die XML in Anführungszeichen gesetzt:

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

nun in diesem Beispiel die JsonResult Variable nimmt tatsächlich eine Zeichenfolge, die mit denen wir arbeiten können. Mit einigen JavaScript-XML-Parsing-Dienstprogrammen könnten wir diese Zeichenfolge in den XML-DOM-Parser laden und damit arbeiten!

Es ist jedoch nicht reines XML, es ist immer noch eine JavaScript-Antwort unter der Haube. Der Antworttyp vom PHP-Server ist immer noch text/javascript, und wir verwenden immer noch ein Skript-Tag, um das zu laden, was eigentlich nur JavaScript ist.

Zusammenfassend könnte man mit "XMLP" oder XML mit Padding arbeiten (ich habe es gerade erfunden, es ist nicht real!), Aber wenn Sie alle Schwierigkeiten machen, Ihre Antwort zu modifizieren Wenn Sie einen Funktions-Callback-Wrapper zurückgeben, können Sie auch einfach Ihre Ausgabe in JSON konvertieren und den Browser automatisch und nativ verarbeiten lassen und sich die Mühe ersparen, einen XML-Parser verwenden zu müssen.

Aber wenn es aus irgendeinem Grund einfacher ist, Ihre Daten im XML-Format zu behalten, können Sie die Antwort ändern und ihr einen JavaScript-Wrapper geben.

Fälle, in denen ich das nützlich finden könnte, wenn XML-Daten aus einer Legacy-Anwendung in einer Datenbank gespeichert sind und Sie diese mithilfe von Script-Tag-Remoting- oder JSONP-Aufrufen an die Clientseite zurückgeben.

+8

das ist sehr praktisch, +1. Sie verdienen Kudos – defau1t

4

Ich fand eine sehr gute Lösung zum Abrufen von XML aus Cross-Domain-Ajax-Anfrage.

Seit jQuery 1.5 können Sie dataType "jsonp xml" (http://api.jquery.com/jQuery.ajax/) verwenden!

So verwenden ich diese:

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

Server-Seite für meine Webservices i verwendet, um das XML-Zeichenfolge Ergebnis innerhalb der Callback von jQuery erstellt einzuzukapseln:

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

und der magischen Methode (i gefunden es in einem anderen Stack-Thread), die Sie benötigen, um Ihre XML-Zeichenfolge zu bereinigen (also Javascript kann es analysieren):

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

Hoffe, das wird helfen!

+9

Ich habe eine 'Uncaught SyntaxError: Unerwarteter Token <' Fehler, wenn ich dies versuchte, zB: '$ .get ('http://www.webservicex.net/geoipservice.asmx/GetGeoIPContext', Funktion (Daten) {console.log (Daten);}, 'jsonp xml'); ' – 10basetom

+2

Dies ist nur nützlich, wenn Sie Zugriff auf den Servercode haben. –