2

thanks in advance for all your help!

i'm fairly new to javascript, but i have a fairly strong background in java, so i thought i would try it out on this project i'm working on.

essentially, what i'm trying to do is read data from an xml file and create the html code for the page i'm making. i used the script from w3schools found here. I've altered it and gotten it to pull the data from my own xml and even to do the more basic generation of the html code i need.

Here's the page i'm using for all my testing / building:

<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>xml test table</title>
<script>
    if (window.XMLHttpRequest)
    {// code for IE7+, Firefox, Chrome, Opera, Safari
        xmlhttp=new XMLHttpRequest();
    }
    else
    {// code for IE6, IE5
        xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
    }

    xmlhttp.open("GET","SWPlanetData.xml",false);
    xmlhttp.send();
    swDoc=xmlhttp.responseXML;
    var s=swDoc.getElementsByTagName("planet");
</script>
</head>
<body>
<div class="planets-info-container"> 
    <script>
            for (i=0;i<s.length;i++)
            {
                var plName
                    = s[i].getElementsByTagName("planetName")[0].childNodes[0].nodeValue;
            var plDesc
                = s[i].getElementsByTagName("description")[0].childNodes[0].nodeValue;
            var plUrl
                = s[i].getElementsByTagName("linkUrl")[0].childNodes[0].nodeValue;
            var plUrlTxt
                = s[i].getElementsByTagName("linkText")[0].childNodes[0].nodeValue;
            var plShowsList
                = s[i].getElementsByTagName("show");
            var plGamesList 
                = s[i].getElementsByTagName("videoGame");

            // test section
            var test = ''
            test += '<div><table border = "1">\n' +
                '<tr><td>' + s[i].getElementsByTagName("showText")[0].childNodes[0].nodeValue
                + '</td><td>' + s[i].getElementsByTagName("showUrl")[0].childNodes[0].nodeValue  + '</td></tr>' 
                + '<tr><td>' + s[i].getElementsByTagName("gameText")[0].childNodes[0].nodeValue + '</td><td>'
                +   s[i].getElementsByTagName("gameUrl")[0].childNodes[0].nodeValue + '</td></tr>'
                + '</tr></table></div>'                 
                document.write(test);
                document.close();
            // end section

            document.write("<div class=\"planet-info-container\" id=\""+plName+"-container\">");
                document.write("<div class=\"name-row\"><div class=\"planet-name\">"+plName+"</div></div>");
                document.write("<div class=\"desc-row\">");
                    document.write("<div class=\"planet-desc\">"+plDesc+"</div>");
                document.write("</div>");
                document.write("<div class=\"appearances-row\"><ol class=\"shows\"><li>shows list</li>");
                for(j=0;j<plShows.length;j++){
                    document.write("nested for");
                    var showUrl = s[i].getElementsByTagName("showUrl")[j].childNodes[0].nodeValue;
                    var showText = s[i].getElementByTagName("showText")[j].childNodes[0].nodeValue;
                    document.write("<li><a href=\""+showUrl+"\">"+showText+"</a></li>");
                }
                document.write("</ol><ol class=\"games\"> games list");
                for(j=0;j<s[i].getElementByTagName("videoGame").length;j++){
                    var gameUrl = s[i].getElementsByTagName("gameUrl")[j].childNodes[0].nodeValue;
                    var gameText = s[i].getElementByTagName("gameText")[j].childNodes[0].nodeValue;
                    document.write("<li><a href=\""+gameUrl+"\">"+gameText+"</a></li>");
                }
                document.write("</ol></div>");
                document.write("<div class=\"locs-row\">");
                document.write("</div>");
                document.write("<div class=\"races-row\">");
                document.write("</div>");
                document.write("<div class=\"chars-row\">");
                document.write("</div>");
                document.write("<div class=\"links-row\">");
                    document.write("<div class=\""+plName+"-link\"><a href=\""+plUrl+"\">"+plUrlTxt+"</a></div>");
                document.write("</div>");
                document.write("</div><br />");
            }
        </script> 
</div>
</body>

the code breaks at the nested for loop at the end, where it finished the document.write and prints "shows list" to the page, but then never gets to the document.write inside.

if it helps, the xml contains a list of planets from the star wars universe organized like this:

<planets>
<planet>
    <planetName>planet</planetName>
    <description>some text</description>
    <appearances>
        <show>
            <showUrl>url</showUrl>
            <showText>hyperlink text</showText>
        </show>
        <videoGame>
            <gameUrl>url</gameUrl>
            <gameText>hyperlink text</gameText>
        </videoGame>
    </appearances>
    <locationsOfInterest>
        <location>location name</location>
    </locationsOfInterest>
    <famousCharactersRelatedTo>
        <character>a character</character>
    </famousCharactersRelatedTo>
    <externalLinks>
        <link>
            <linkUrl>url</linkUrl>
            <linkText>hyperlink text</linkText>
        </link>
    </externalLinks>
</planet>

edit: i made this harder than it had to be by trying to cut the code down to reduce clutter, but i left out some important things / misordered what i put in, so i replaced the code i had before with the entire page as-is.

edit again: i've made some progress, but i'm still having trouble with the nested loops. it will enter the first one, but breaks before getting all the way through the first iteration on setting the second var:

var showText = s[i].getElementsByTagName("showText")[j].childNodes[0].nodeValue;

can anyone see why this would break?

7
  • 1
    Where it says j<plShows.length did you mean j<plShowsArr.length? Commented Sep 17, 2012 at 3:38
  • var plShowsArr = s[i].getElementsByTagName("show"); where does i come from Commented Sep 17, 2012 at 3:38
  • then the following loop uses the i again? Commented Sep 17, 2012 at 3:40
  • 1
    That being said: mcdwight6 needs to employ the fix irrelephant mentioned and remove the [i] from the line Marcus mentioned, as well as removing the [i] from the line succeeding it. Commented Sep 17, 2012 at 3:45
  • 1
    Anything in the console? Likely not related but w3fools.com - it is not recommended to use document.write in a loop. Instead append to a string and use innerHTML instead. If you call your function after page rendering, then that WILL break the page with document.write Commented Sep 17, 2012 at 3:48

3 Answers 3

2

In your code:

> var s = swDoc.getElementsByTagName("planet");

Hopefully swDoc is a reference to an XML document.

> var plShowsArr = s[i].getElementsByTagName("show");

You haven't shown where i is declared or initialised, so I'd expect an error here. Also, the name plShowsArr infers that you think it's an array, it isn't, getElementsByTagName returns a NodeList, which is similar to an array in that it has a self–adjusting length property and the members can be accessed by index. But that's where the similarity ends.

> document.write("<div><table border = \"1\">");

You can nest single and double quotes to avoid quoting, e.g.

  document.write('<div><table border="1">');

but using document.write this way is less than optimal. If the document has finished loading, then a call to document.write will first clear the entire document before writing the new content. In any case, it's much more efficient to create a single string of markup, then either use document.write (if that is appropriate) or set the markup as the innerHTML of some container element.

So you might do:

var markup = ''
...
  markup += '<div><table border="1">';

...
// If writing to a child window
document.write(markup);
document.close();

// If assigning to the innerHTML of a container element
var container = document.getElementById('containerID');
if (container) {
  container.innerHTML = markup;
}

Later you have:

> document.write('<div class="appearances-row"><ol class="shows">shows list');

This inserts a text node as the child of an OL element. That's not allowed, whatever happens next is implementation dependent, your guess is as good as mine. You have left the user agent in limbo.

Then:

>  for(j=0;j<plShows.length;j++){

Another undeclared variable: j becomes a global variable when this line is executed.

I haven't analysed what the counters are doing, I'll leave that to you.

Edit

Use of a debugger (Firebug in Firefox will do) shows the following:

  1. The XML is missing a closing planets tag

  2. Don't use document.close until you are finished all writing to the document, it's not necessary when using document.write while a document is loading and there is more to load after the script.

  3. In the line for (j=0; j<plshows.length; j++){, variable plshows is not defined, replace with plShowsList

  4. In the line document.write("</ol><ol class=\"games\"> games list"); an LI should be inserted after the OL and before the text.

  5. In the line var showText = s[i].getElementByTagName..., the reference s[i] does not have a method getElementByTagName, the method is getElementsByTagName (there are two lines with this error — copy paste?)

Add a bit of white space to your code, it's very unreadable. And change all those document.writes to a concatenated string and insert once as the div's innerHTML (move the script to immediately after the div).

Fix all the above and it "works". Your invoice is in the mail...

Sign up to request clarification or add additional context in comments.

3 Comments

you're right in that there would be several errors thrown throughout what i posted of my code. i tried to copy and paste the pertinent pieces to reduce clutter, but it seems i misordered a few things. i do like what you're saying about concatenating the markup to make it less taxing, though. i'll see what i can do with that. so you think the problem with the nested for loop is that the j isn't initialized previously?
I don't know why it's not working, it shouldn't be about the j variable, more likely related to the use of document.write and invalid markup.
i think i fixed some of the problems just with using the concat then printing. it will enter the show loop, but it breaks before completing the first iteration. i've tried using s[i] as well as switching it out to try and reference it from the plShowsList, but to no avail. any ideas?
1

At minimum I think you need two changes.

Move the following two lines:

var plShowsArr = s[i].getElementsByTagName("show");
var plGamesArr = s[i].getElementsByTagName("videoGame");

...to inside the outer for loop. Both lines are trying to access children of the current "planet" element as indexed by the i variable.

Update the inner for statement which at the moment is using plShows.length but should be using plShowsArr.length.

Optionally the inner loop can be improved by selecting the "showUrl" and "showText" from within the current "show" rather than selecting them from within the current "planet":

       for(j=0;j<plShowsArr.length;j++){
            document.write("nested for");
            var showUrl = plShowsArr[j].getElementsByTagName("showUrl")[0].childNodes[0].nodeValue;
            var showText = plShowsArr[j].getElementByTagName("showText")[0].childNodes[0].nodeValue;
            document.write("<li><a href=\""+showUrl+"\">"+showText+"</a></li>");
        }

A number of other improvements could be made, but they're (probably?) not directly related to your current problem.

Comments

0

in case you're wondering, this was a dumb on my part. the big difference between

var showUrl = plShowsArr[j].getElementsByTagName("showUrl")[0].childNodes[0].nodeValue;

and

var showText = plShowsArr[j].getElementByTagName("showText")[0].childNodes[0].nodeValue;

lies right here:

how to be code like a n00b....

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.