【问题标题】:XMLHttpRequest loads XML from local server but not from external server?XMLHttpRequest 从本地服务器而不是从外部服务器加载 XML?
【发布时间】:2018-07-09 02:28:49
【问题描述】:

我已多次尝试从外部服务器加载XML,但均未成功。

第一个示例在我的服务器上有XML document 时完美地加载了XML,但当我尝试从外部服务器加载相同的XML 时却没有。

第二个示例正在从外部服务器上加载XML,但在我的页面上加载的数据与 XML 不同。

我的XMLHttpRequest 中是否遗漏了什么,或者这是Cross Origin 的问题?

编辑:第二个示例通过将responseText 更改为responseXML 解决,但是第一个示例已经有responseXML,但它不起作用。为什么第一个示例的功能与第二个示例不同?

第一个例子

var n = document.getElementById("search");
n.addEventListener("keyup", function(event) {
    event.preventDefault();
    if (event.keyCode === 13) {
        document.getElementById("myButton").click();
    }
});
    
function loadDoc(url, cFunction) {
  var xhttp;
  xhttp=new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      cFunction(this);
    }
  };
  xhttp.open("GET","https://www.w3schools.com/xml/books.xml", true);
  xhttp.send();
}
    
function myFunction(xhttp) {
var a = n.value;

var xmlDoc = xhttp.responseXML;
const { value } = search;
const foundState = [...xmlDoc.querySelectorAll('title')].find(possibleMatch => possibleMatch.textContent === value);
const unit = foundState.parentElement;
console.log(unit.innerHTML);
document.getElementById("titleNode").innerHTML = unit.children[0].textContent;
document.getElementById("authorNode").innerHTML = unit.children[1].textContent;
document.getElementById("yearNode").innerHTML = unit.children[2].textContent;
}
<input type="text" name="search" id="search"  placeholder="type 'r'" list="searchresults" autocomplete="off" />

<datalist id="searchresults">
<option value="Everyday Italian">001</option>
<option value="XQuery Kick Start">010</option>
<option value="Learning XML">110</option>
<option value="Harry Potter">101</option>
</datalist>

<button id="myButton" type="button"
onclick="loadDoc('https://www.w3schools.com/xml/books.xml', myFunction)">Submit
</button>

<p>Title node: <span id="titleNode"></span></p>
<p>Author node: <span id="authorNode"></span></p>
<p>Year node: <span id="yearNode"></span></p>

第二个例子

function loadDoc(url, cFunction) {
  var xhttp;
  xhttp=new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      cFunction(this);
    }
  };
  xhttp.open("GET", "https://data.cityofnewyork.us/api/views/kku6-nxdu/rows.xml", true);
  xhttp.send();
}
function myFunction(xhttp) {
  document.getElementById("demo").innerHTML =
  xhttp.responseXML;
}
<div id="demo">

<h2>The XMLHttpRequest Object</h2>

<button type="button"
onclick="loadDoc('ajax_info.txt', myFunction)">Change Content
</button>
</div>

【问题讨论】:

  • 如果你的响应是 XML,不要使用responseText,使用responseXML。而且,在调试 AJAX 调用时,请始终打开开发人员工具的 Network 选项卡,因为它会准确显示正在发生的事情。另外,请注意CORS,默认情况下会阻止跨域请求。
  • 谢谢,第一个示例已经使用了 responseXML,但不起作用。我更新了第二个示例以也使用 responseXML,并且该示例现在似乎可以工作。我没听懂。
  • 您的第一个示例在onreadystatechange 上调用cFunction(this);,但您没有声明该函数。你确实有myFunction,但它永远不会被调用。

标签: javascript ajax xml xmlhttprequest


【解决方案1】:

您的预感是正确的,这就是同源政策!一些服务器设置为允许跨域资源共享 (CORS),但这种情况非常罕见。如果您想设置您的一个网站/服务器以允许另一个 Ajax 请求访问,您可以关注此MDN guide

编辑:Scott Marcus 对您的代码是正确的。

关于你的第二个问题:

我运行了您的代码并在控制台中收到此错误:

跨域请求被阻止:同源策略不允许读取位于https://www.w3schools.com/xml/books.xml 的远程资源。 (原因:缺少 CORS 标头“Access-Control-Allow-Origin”)。

w3schools 没有启用 CORS。

查看this thread 以及那里发布的链接,以找到规避同源政策的方法。

【讨论】:

  • 我对第二个示例进行了更正,该示例现在可以正常工作了——可能是因为您所说的某些站点是为 CORS 设置的?
  • 是的,这在大多数网站中并不常见。我想它被称为纽约市“开放数据!” :)
  • 那么如果没有启用CORS,是否没有可接受的方式通过XMLHttpRequest从外部访问XML?
  • @Scott Marcus,即“同源策略”。从我发布的 MDN 文档中:“跨域资源共享 (CORS) 是一种机制,它使用额外的 HTTP 标头告诉浏览器让在一个源(域)上运行的 Web 应用程序有权访问来自服务器的选定资源不同的起源。“
  • @logoologist 我编辑了我的答案,包括一个可能有用的 SO 链接,供您探索一些绕过它的方法。
猜你喜欢
  • 1970-01-01
  • 2015-07-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-23
  • 2012-03-21
  • 1970-01-01
相关资源
最近更新 更多