1

I've made various attempts to load XML from external servers, but without success.

The first example loads the XML perfectly when I have the XML document on my server, but not when I try loading the same XML from the external server.

The second example is loading XML from on an external server, but the data that loads on my page doesn't resemble XML.

Am I missing something in my XMLHttpRequest, or is this the Cross Origin problem?

EDIT: The second example was solved by changing responseText to responseXML, however the first example already has responseXML and yet it doesn't work. Why won't the first example function in the same manner as the second example?

first example

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>

second example

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>
logoologist
  • 205
  • 3
  • 15
  • 2
    If your response is XML, don't use `responseText`, use `responseXML`. And, always have the Network tab of your developer's tools open when debugging AJAX calls because it will show you exactly what's happening. Also, be aware of [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS), which will block cross-origin requests by default. – Scott Marcus Jul 08 '18 at 03:19
  • Thanks, the first example already uses responseXML, but doesn't work. I updated the second example to also use responseXML, and that one appears to work now. I didn't catch that. – logoologist Jul 08 '18 at 03:27
  • Your first example calls `cFunction(this);` on `onreadystatechange`, but you don't have that function declared. You do have `myFunction`, but it never gets called. – Scott Marcus Jul 08 '18 at 14:44

1 Answers1

1

Your hunch is correct, this is the Same-Origin Policy in action! Some servers are set up to allow Cross-Origin Resource Sharing (CORS), but that is pretty rare. If you would like to set up one of your websites/servers to allow another Ajax request access, you can follow this MDN guide.

Edit: Scott Marcus is correct about your code.

About your second question:

I ran your code and got this error in the console:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://www.w3schools.com/xml/books.xml. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).

w3schools does not have CORS enabled.

Take a look at this thread and the links posted there to find a way to circuimvent the Same Origin Policy.

dandeto
  • 756
  • 6
  • 13
  • I made that correction to the second example, which is now working -- probably because as you stated some sites are set up for CORS? – logoologist Jul 08 '18 at 03:28
  • Yes, that is not typical of most websites. I suppose it is called NYC "Open Data!" :) – dandeto Jul 08 '18 at 04:02
  • So if CORS is not enabled, is there no acceptable way of accessing the XML externally through XMLHttpRequest? – logoologist Jul 08 '18 at 05:24
  • @Scott Marcus that is the “Same Origin Policy.” From the MDN Doc I posted: “Cross-Origin Resource Sharing (CORS) is a mechanism that uses additional HTTP headers to tell a browser to let a web application running at one origin (domain) have permission to access selected resources from a server at a different origin.“ – dandeto Jul 08 '18 at 18:26
  • @logoologist I edited my answer to include a potentially helpful SO link for you to explore some ways to get around it. – dandeto Jul 08 '18 at 18:30
  • thanks for the info. If XMLHttpRequest is so problematic, is there a protocol to simply instruct my server to download the external XML file to my local server? – logoologist Jul 13 '18 at 03:46
  • Not that I am aware of. I did some intense googling on the subject; however, I was unable to find anything like that. You could manually download the XML file from a website and put it on your server. Ajax is the only way I know of that you can load external resources like XML with. – dandeto Jul 14 '18 at 04:55
  • Or perhaps I could use PHP to automatically download an external file to my server? – logoologist Jul 14 '18 at 17:19
  • I don't know. This might help: https://stackoverflow.com/questions/3938534/download-file-to-server-from-url Otherwise just ask a new question. Have I answered your question to your satisfaction? – dandeto Jul 14 '18 at 18:48
  • Of course, thanks so much for your thoughts on this issue. – logoologist Jul 14 '18 at 21:16