【问题标题】:javascript won't execute nested for loopjavascript不会执行嵌套的for循环
【发布时间】:2012-09-09 07:00:09
【问题描述】:

提前感谢您的帮助!

我是 javascript 的新手,但我在 java 方面有相当深厚的背景,所以我想我会在我正在从事的这个项目上尝试一下。

本质上,我要做的是从 xml 文件中读取数据并为我正在制作的页面创建 html 代码。我使用了来自 w3schools 的脚本 here。我已经对其进行了修改并让它从我自己的 xml 中提取数据,甚至可以生成我需要的更基本的 html 代码。

这是我用于所有测试/构建的页面:

<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>

代码在最后的嵌套 for 循环处中断,它完成了 document.write 并将“显示列表”打印到页面,但随后再也没有到达 document.write 内部。

如果有帮助,xml 包含来自星球大战宇宙的行星列表,其组织方式如下:

<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>

编辑:我试图减少代码以减少混乱,使这变得比原来更难,但我遗漏了一些重要的东西/我输入的内容有误,所以我用整个代码替换了我之前的代码页面原样。

再次编辑:我已经取得了一些进展,但我仍然遇到嵌套循环的问题。它将进入第一个,但在设置第二个变量的第一次迭代之前中断:

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

谁能明白为什么这会坏?

【问题讨论】:

  • 上面写着j&lt;plShows.length的意思是j&lt;plShowsArr.length吗?
  • var plShowsArr = s[i].getElementsByTagName("show");我从哪里来
  • 那么下面的循环又使用了 i 吗?
  • 话虽如此:mcdwight6 需要使用提到的修复无关紧要,并从 Marcus 提到的行中删除 [i],并从后面的行中删除 [i]
  • 控制台中有什么东西吗?可能不相关,但 w3fools.com - 不建议在循环中使用 document.write。而是附加到字符串并改用 innerHTML。如果你在页面渲染后调用你的函数,那么将会用 document.write 破坏页面

标签: javascript html xml for-loop xmlhttprequest


【解决方案1】:

在您的代码中:

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

希望 swDoc 是对 XML 文档的引用。

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

您还没有显示i 的声明或初始化位置,所以我预计这里会出现错误。此外,名称plShowsArr 暗示您认为它是一个数组,它不是,getElementsByTagName 返回一个NodeList,它与数组类似,它具有自调整长度属性并且成员可以是通过索引访问。但这就是相似性结束的地方。

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

您可以嵌套单引号和双引号以避免引用,例如

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

但以这种方式使用document.write 并不是最佳选择。如果文档已完成加载,则调用document.write 将首先清除整个文档,然后再写入新内容。在任何情况下,创建单个标记字符串会更有效,然后使用 document.write(如果合适的话)或将标记设置为某个容器元素的 innerHTML。

所以你可以这样做:

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;
}

稍后你有:

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

这会插入一个文本节点作为 OL 元素的子节点。这是不允许的,接下来发生的任何事情都取决于实现,你的猜测和我的一样好。你让用户代理陷入了困境。

然后:

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

另一个未声明的变量:j在执行此行时成为全局变量。

我还没有分析计数器在做什么,我将把它留给你。

编辑

使用调试器(Firefox 中的 Firebug 可以)显示如下:

  1. XML 缺少关闭行星标记

  2. 在完成对文档的所有写入之前不要使用document.close,在加载文档时使用document.write 并在脚本之后加载更多内容时没有必要。

  3. for (j=0; j&lt;plshows.length; j++){行中,变量plshows未定义,替换为plShowsList

  4. document.write("&lt;/ol&gt;&lt;ol class=\"games\"&gt; games list"); 行中,应在OL 之后和文本之前插入一个LI。

  5. var showText = s[i].getElementByTagName...行中,引用s[i]没有方法getElementByTagName,方法是getElementsByTagName(有两行出现这个错误——复制粘贴?)

在您的代码中添加一些空白,它非常难以阅读。并将所有这些 document.writes 更改为连接字符串并作为 div 的 innerHTML 插入一次(将脚本移动到 div 之后)。

修复以上所有问题,它“工作”。您的发票在邮件中...

【讨论】:

  • 你是对的,在我发布的代码中会抛出几个错误。我试图复制和粘贴相关的部分以减少混乱,但似乎我弄错了一些东西。不过,我确实喜欢你所说的关于连接标记以减少税收的说法。我会看看我能用它做什么。所以你认为嵌套 for 循环的问题是 j 之前没有初始化?
  • 我不知道为什么它不起作用,它不应该与j变量有关,更可能与document.write的使用和无效标记有关。
  • 我想我解决了一些问题,只是使用 concat 然后打印。它将进入显示循环,但在完成第一次迭代之前它会中断。我尝试使用 s[i] 以及将其切换为尝试从 plShowsList 中引用它,但无济于事。有什么想法吗?
【解决方案2】:

我认为您至少需要进行两项更改。

移动以下两行:

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

...到 inside 外部 for 循环。这两行都试图访问由i 变量索引的当前“planet”元素的子元素。

更新内部for 语句,该语句目前使用plShows.length,但应该使用plShowsArr.length

可选地,可以通过从当前“show”中选择“showUrl”和“showText”来改进内部循环,而不是从当前“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>");
        }

可以进行许多其他改进,但它们(可能?)与您当前的问题没有直接关系。

【讨论】:

    【解决方案3】:

    如果您想知道,这对我来说是个愚蠢的行为。最大的区别

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

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

    就在这里:

    【讨论】:

      猜你喜欢
      • 2014-11-13
      • 1970-01-01
      • 2016-11-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多