2012-04-09 28 views
20

Tôi làm cách nào để khắc phục sự cố tên miền chéo khi phân tích cú pháp XML từ một máy chủ/miền khác? Ai đó có thể cung cấp cho tôi một ví dụ? Ví dụ này không phải bị hạn chế đối với jQuery, vì JavaScript cũng sẽ đủ.Làm thế nào để phân tích cú pháp XML Cross-domain trong jQuery?

+0

ý của bạn là gì bởi crossdomain –

+1

Chỉ thực thi tên miền chéo được phép từ JavaScript là JSONP. – AlienWebguy

+0

"Yêu cầu tập lệnh và JSONP không tuân theo cùng các hạn chế chính sách gốc." –

Trả lời

66

Để hiểu đầy đủ lý do tại sao tinh khiết XML đa miền sẽ không hoạt động, trước hết, hãy xem xét cách thức tạo JSON tên miền chéo.

Đầu tiên, chúng ta hãy nhìn vào những gì sẽ xảy ra khi bạn thực hiện một yêu cầu AJAX trong jQuery:

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

Trong ví dụ trên, yêu cầu AJAX được thực hiện liên quan đến tên miền. Chúng tôi biết rằng nếu chúng tôi cố thêm một miền khác trước đường dẫn, yêu cầu sẽ không thành công với ngoại lệ bảo mật.

Tuy nhiên, điều đó không có nghĩa là trình duyệt không thể đưa ra yêu cầu cho miền khác. Dưới đây là một ví dụ mà bạn có thể quen thuộc với bạn:

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

Dựa trên sự hiểu biết của chúng ta về cách nhập JavaScript trên trang web, chúng ta thấy rằng nó có thể tải một tài nguyên mà tồn tại trên tên miền khác!

JSONP là một khái niệm khai thác kiến ​​thức này. JSONP là viết tắt của "JSON với padding", và thành công của nó dựa trên thực tế là các đối tượng JavaScript có thể được biểu diễn bằng ký hiệu chuỗi và thực tế là các thẻ JavaScript script có thể tải và chạy nội dung từ các miền bên ngoài.

Dưới mui xe, JSONP jQuery trông giống như thế này mặc dù nó có thể không chính xác:

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

Ngoài ra, trên trang nơi nào đó, chúng ta định nghĩa một handler callback:

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

Ở đây, chúng tôi đưa ra yêu cầu:

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

Để làm việc này đúng, tập lệnh PHP của chúng tôi phải cả hai đều trả về dữ liệu ở định dạng JSON và cũng phải thêm "đệm" xung quanh chuỗi dưới dạng tên hàm JavaScript mà chúng tôi có thể truyền vào dưới dạng tham số (tức là "Gọi lại")

Như vậy, phản hồi từ máy chủ có thể trông giống như thế này, nếu chúng ta nhìn vào nó trong Firebug hoặc Chrome tab NET:

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

Bởi vì chúng ta đều biết nội dung Javascript chạy như ngay sau khi được tải xuống, hàm processData mà chúng tôi đã xác định trước đó được gọi ngay và được chuyển qua chuỗi JSON của chúng tôi dưới dạng thông số. Sau đó nó được cảnh báo, sử dụng JSON.stringify để chuyển đổi đối tượng trở lại thành một chuỗi.

Vì nó là một đối tượng, tôi cũng có thể truy cập nó là tài sản, như vậy:

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

Cuối cùng, chúng ta hãy chuyển sang câu hỏi chính: thể JSONP được sử dụng để truy xuất XML, hoặc chúng ta có thể phân tích cú pháp XML chéo -miền? Câu trả lời, như những người khác đã chỉ ra, là một vang dội NO, nhưng chúng ta hãy nhìn vào lý do tại sao bằng cách sử dụng một ví dụ:

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

Bây giờ, điều gì sẽ xảy ra nếu XML thô được chuyển vào chức năng? Nó sẽ phá vỡ, vì JavaScript không có cách nào để chuyển đổi XML thành JSON.

Tuy nhiên, giả sử chúng ta đặt XML trong dấu ngoặc kép:

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

Bây giờ, trong ví dụ này, biến JsonResult thực sự phải mất một chuỗi, mà chúng tôi có thể làm việc với. Sử dụng một số tiện ích phân tích cú pháp XML JavaScript, chúng ta có thể tải chuỗi đó vào trình phân tích cú pháp XML DOM và thực hiện các công cụ với nó!

Tuy nhiên, nó không phải là XML thuần túy, nó vẫn là một phản ứng JavaScript dưới mui xe. Loại phản hồi từ máy chủ PHP vẫn là văn bản/javascript và chúng tôi vẫn đang sử dụng thẻ tập lệnh để tải những gì thực sự là JavaScript đơn giản.

Tóm lại, bạn có thể làm việc với "XMLP" hoặc XML với đệm (tôi vừa tạo ra nó, nó không thực sự!), Nhưng nếu bạn đang đi qua tất cả các rắc rối thực sự sửa đổi phản hồi của bạn trả về một hàm gọi lại hàm, bạn cũng có thể chuyển đổi đầu ra của bạn thành JSON và để cho trình duyệt xử lý các chuyển đổi một cách tự động và nguyên bản và tiết kiệm cho mình những rắc rối khi phải sử dụng một trình phân tích cú pháp XML.

Nhưng nếu vì một lý do nào đó để giữ dữ liệu của bạn ở định dạng XML dễ dàng hơn, bạn có thể sửa đổi phản hồi và cung cấp cho nó trình bao bọc JavaScript.

Các trường hợp mà tôi có thể thấy điều này hữu ích có thể là nếu bạn có dữ liệu XML từ ứng dụng cũ được lưu trữ trong cơ sở dữ liệu và bạn trả về phía máy khách bằng cách sử dụng tính năng gọi lại từ xa hoặc gọi hàm JSONP.

+8

rất tiện dụng, +1. bạn xứng đáng nhận được kudo – defau1t

4

Tôi đã tìm thấy giải pháp rất tốt để truy xuất xml từ yêu cầu ajax miền chéo.

Vì jQuery 1.5 bạn có thể sử dụng dataType "jsonp xml" (http://api.jquery.com/jQuery.ajax/)!

Vì vậy, tôi sử dụng này: phía

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

Server cho Webservices của tôi sử dụng để đóng gói các kết quả chuỗi xml trong callback được tạo ra bởi 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); 
     } 

và phương pháp kỳ diệu (i tìm thấy trong một chuỗi ngăn xếp khác) mà bạn sẽ cần phải khử trùng chuỗi xml của mình (để javascript có thể phân tích cú pháp):

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

Hy vọng điều này sẽ giúp bạn!

+9

Tôi nhận được lỗi "Cú pháp không được bắt buộc: Lỗi không mong muốn <' khi tôi thử điều này, ví dụ: '$ .get ('http://www.webservicex.net/geoipservice.asmx/GetGeoIPContext', hàm (dữ liệu) {console.log (dữ liệu);}, 'jsonp xml'); ' – 10basetom

+2

Điều này chỉ hữu ích khi bạn có quyền truy cập vào mã máy chủ. –

Các vấn đề liên quan