简体   繁体   中英

XML Document “undefined” in JavaScript

I'm working on an HTML5 implementation of a game idea I'm playing with. Part of this, naturally, is storing the content, among which is the data for different abilities in the game, as well as characters and such.

While dynamic content, such as specific characters, will be moved later on, I will probably stick to XML for static content, such as stats for abilities and gear, which means I'd prefer fixing the issues I'm having with XML as soon as possible.

Now, to do this, I'm loading in XML documents at the beginning of a combat phase, first the character, then the abilities etc relevant to this character.

To do this, I have a "loadXMLFile" function, that takes a filename:

var loadXMLFile = function(filename) {
  req = new XMLHttpRequest();
  req.onreadystatechange = function() {
    return req.responseXML;
  }
  req.open("GET", filename, true);
  req.send();
}

An example of loading and manipulating the data:

function Character(id) {
  doc = loadXMLFile("characters.xml");
  characters = doc.getElementsByTagName("Character");

My intention with this was to make the function call wait for the return value before continuing. As you may be able to tell from the title of the question, this does not work. Instead, as soon as I attempt to manipulate the data, the third line in the example, I receive the following runtime error: Uncaught TypeError: Cannot call method 'getElementsByTagName' of undefined

As the example shows, I load these XML files in my constructors, using the XML file to populate the class. Hence, a structure of calling a different function inside the readystatechange event handler is less than preferable. Am I forced to repeat the XML loading code everywhere I do this, just to make separate event handlers?

I would suggest to use jQuery or another javascript framework. It's much easier to handle problems like this and you will save a lot of time and code lines. Another problem is the cross-browser compatibility which is not given in your code.

You want to change:

req.open("GET", filename, true);

To:

req.open("GET", filename, false);

To make a synchronous request (which means wait for the request before continuing.)

You can not return something from onreadystatechange, that part of your code is wrong.

And you are not checking what the actual state is in that function, so that's wrong too.

So basically your code is not correct at all. I would suggest finding a tutorial site for XMLHttpRequest and copying their code.

As a side note, why are you making life hard for yourself? Install jQuery and let it do all this stuff for you.

And a final note, json is a LOT easier to work with than xml, you may want to switch to that.

The piece of code that was mentioned is browser specific issue. You should ideally be using the cross-browser compatible javascript based frameworks. You can avoid most of the cross-browser related issues.

Coming to resolution of your issue, getElementsByTagName function is not available within the doc element. So, you can modify the code in the following manner,

if(doc.getElementsByTagName){
     characters = doc.getElementsByTagName("Character");
}

But this will only avoid the error but will not resolve the issue of getting the Character element.

The best option would be to convert the XML to JSON in the server and send the JSON to the client. It is easy to traverse through the JSON easily and there are no cross-browser issues.

One can traverse through the JSON easily as follows,

function traverseJSON (jsonObj){
    for(var value in jsonObj){
        if(typeof value == 'function'){//this is to avoid 'remove' function in case of Array, Array object will be available in case of repeating elements in XML. 
            continue;
        }else if(typeof value == 'object'){ //refers to element in XML 
            traverseJSON(value);
        }else if(typeof value== 'string'){   //refers to attribute in XML
        jsonObj[value]; //refers to the attribute value in XML
        }
    }
}

The above function can be used to traverse through the JSON, which takes JSON object as the input.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM