要充分理解为什么pure跨域 XML 不起作用,首先了解一下跨域 JSON 是如何促进的会有所帮助。
首先,让我们看看当您在 jQuery 中发出 AJAX 请求时会发生什么:
$.ajax({
url: '/user.php?userId=123',
success: function(data) {
alert(data); // alerts the response
});
在上面的示例中,AJAX 请求是相对于域发出的。我们知道,如果我们尝试在路径之前添加不同的域,请求将失败并出现安全异常。
但是,这并不是说浏览器不能向另一个域发出请求。以下是您可能熟悉的示例:
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
根据我们对如何在页面上导入 JavaScript 的了解,我们发现可以加载另一个域中存在的资源!
JSONP 是一个利用这些知识的概念。 JSONP 代表“带有填充的 JSON”,它的成功取决于 JavaScript 对象可以使用字符串表示法来表达,以及 JavaScript 脚本标签可以加载和运行来自外部域的内容。
在底层,jQuery 的 JSONP 看起来像这样,尽管可能不准确:
// 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);
}
另外,在页面的某个地方,我们定义了一个回调处理程序:
function processData(jsonResult) {
alert(JSON.stringify(jsonResult)); //alert the JSON as a string
}
在此,我们提出要求:
// make a request for the data using the script tag remoting approach.
loadRemoteData("http://example.com/users.php?userId=123&callback=processData");
为了使其正常工作,我们的 PHP 脚本必须以 JSON 格式返回数据,并且还必须以 JavaScript 函数名称的形式在字符串周围添加“填充”,我们可以将其作为参数传入(即“回调”) )
因此,如果我们在 Firebug 或 Chrome NET 选项卡中查看,服务器的响应可能如下所示:
processData( { "userId" : "123" , "name" : "James" , "email" : "[email protected]" } );
因为我们知道 JavaScript 内容一旦下载就会运行,我们的processData
我们之前定义的函数会立即被调用,并将 JSON 字符串作为参数传递。然后它会收到警报,使用 JSON.stringify 将对象转换回字符串。
由于它是一个对象,我还可以访问它的属性,如下所示:
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);
}
最后,让我们进入主要问题:是否可以使用JSONP来获取XML,或者我们可以跨域解析XML吗?正如其他人指出的那样,答案是否定的,但让我们通过一个例子来看看为什么:
processData(<?xml version="1.0"><user><userid>12345</userid><name>James</name><email>[email protected]</email></user>);
现在,如果将原始 XML 传递到函数中会发生什么?它会崩溃,因为 JavaScript 无法将 XML 转换为 JSON。
但是,假设我们将 XML 放在引号中:
processData("<?xml version="1.0"><user><userid>12345</userid><name>James</name><email>[email protected]</email></user>");
现在,在这个例子中, jsonResult 变量实际上接受一个字符串,我们可以使用它。使用一些 JavaScript XML 解析实用程序,我们可以将该字符串加载到 XML DOM 解析器中并用它做一些事情!
然而,它不是纯 XML,它仍然是底层的 JavaScript 响应。 PHP 服务器的响应类型仍然是文本/javascript,并且我们仍然使用脚本标记来加载实际上只是纯 JavaScript 的内容。
总之,您可以使用“XMLP”或带填充的 XML(我只是编造的,这不是真的!),但是如果您要经历实际修改响应以返回函数回调的所有麻烦包装器,您也可以将输出转换为 JSON,并让浏览器自动本地处理转换,从而省去使用 XML 解析器的麻烦。
但是,如果由于某种原因以 XML 格式保存数据更容易,您可以修改响应并为其提供 JavaScript 包装器。
我认为这很有用的情况可能是,如果您将来自遗留应用程序的 XML 数据存储在数据库中,并且您使用脚本标记远程处理或 JSONP 调用将其返回到客户端。