【问题标题】:Looping through XML with jQuery使用 jQuery 循环遍历 XML
【发布时间】:2009-10-15 18:11:22
【问题描述】:

我有一些基本代码可以循环访问从 Adob​​e RoboHelp 生成的一些 XML(用于我们的帮助文档)。这很好用,但由于一个主题可以嵌套任意多次,我需要一种更好的方法来循环这个 XML,而不是仅仅嵌套 .each() 循环。

这是 XML 的样子

<?xml version="1.0" encoding="utf-8"?>
<!--RoboML: Table of Content-->
<roboml_toc>
  <page title="Welcome" url="Welcome.htm"/>
 <book title="Getting Started" url="Getting_Started/Initial_Setup.htm">
   <page title="Initial Setup" url="Getting_Started/Initial_Setup.htm"/>
   <page title="Customize Settings" url="Getting_Started/Settings.htm"/>
 </book>
 <book title="Administrator Services" url="Administrator_Services/General_Administrator.htm">
  <book title="Portal Workspace" url="Administrator_Services/Portal_Workspace/AdminHome.htm">
    <page title="Home" url="Administrator_Services/Portal_Workspace/AdminHome.htm"/>
    <page title="Portal Accounts" url="Administrator_Services/Portal_Workspace/Portal_Accounts.htm"/>

  </book>
  <book title="SpamLab" url="Administrator_Services/SpamLab/SpamLab_Admin_General.htm">
    <page title="Alerts" url="Administrator_Services/SpamLab/Alerts.htm"/>
    <page title="Spam Quarantine" url="Administrator_Services/SpamLab/Admin_Spam_Quarantine_.htm"/>

  </book>

 </book>
 <book title="User Services" url="User_Services/General_User.htm">
  <book title="Portal Workspace" url="User_Services/Portal_Workspace/Home.htm">
    <page title="Home" url="User_Services/Portal_Workspace/Home.htm"/>
    <page title="Self Help" url="User_Services/Portal_Workspace/Self_Help.htm"/>
  </book>
  <book title="SpamLab" url="User_Services/SpamLab/SpamLab_General.htm">
    <page title="Spam Quarantine" url="User_Services/SpamLab/Spam_Quarantine.htm"/>
    <page title="Virus Quarantine" url="User_Services/SpamLab/Virus_Quarantine.htm"/>
  </book>

  <book title="Encryption" url="User_Services/Encryption/Encryption_General.htm">
    <page title="Outlook Plug-in" url="User_Services/Encryption/Encryption_Outlook_Plug_in.htm"/>
  </book>
 </book>
</roboml_toc>

&lt;page&gt; 是一篇文章,&lt;book&gt; 是一个文件夹。

她是我的 jQuery 代码,只能看一级标签

   //Get the TOC
$tocOutput="";
$.get(tocURL,function(toc){
    $(toc).children().each(function(){
        $tocOutput+="<li><a href='"+$(this).attr("url")+"'>"+$(this).attr("title")+"</a>";
        if(this.tagName=="BOOK"){
            $tocOutput+="<ul>";
            $(this).find("page").each(function(){
                $tocOutput+="<li><a href='"+$(this).attr("url")+"'>"+$(this).attr("title")+"</a></li>";
            });
            $tocOutput+="</ul>";
        }
        $tocOutput+="</li>";
    });
    $("#list").html($tocOutput);

我知道有一种更好的方法可以遍历所有元素,然后确定该元素是否有子元素等,但我就是想不出该怎么做。

非常感谢任何帮助!

【问题讨论】:

  • 只是好奇 - 为什么必须在客户端上执行此操作?为什么不在服务器上应用 XSLT 转换并发送 html? xml是动态的吗?转换后的html会不会缓存在服务器上?
  • 无论如何,很高兴您找到了解决方案 - 现在接受 KEITH 的回答 :)
  • 我拒绝!现在这只是一个概念证明......实际上我只是想给一些人留下深刻印象。他们现在对我赞不绝口,所以这是值得的。最终我认为我们会做这个服务器端。

标签: jquery xml loops robohelp


【解决方案1】:

递归函数可以很好地解决这个问题。当您创建一个创建和使用内部递归闭包的函数时,您可以将其全部包装在一个简洁的小包中:

    $.get(tocURL, function(toc) {
    function makeToc($xml) {
        // variable to accumulate markup
        var markup = "";
        // worker function local to makeToc
        function processXml() {
            markup += "<li><a href='" + $(this).attr("url") + "'>" + $(this).attr("title") + "</a>";
            if (this.nodeName == "BOOK") {
                markup += "<ul>";
                // recurse on book children
                $(this).find("page").each(processXml);
                markup += "</ul>";
            }
            markup += "</li>";
        }
        // call worker function on all children
        $xml.children().each(processXml);
        return markup;
    }
    var tocOutput = makeToc($(toc));
    $("#list").html(tocOutput);
});

【讨论】:

    【解决方案2】:

    你可以使用

    $(el).children().length 将返回 '0' 或正数,如果它是正数且计算结果为真,则循环遍历。您也可以使用 while 循环递归地执行此操作,并重新设置引用处理程序,但是我不太确定这会奏效,因为您的每个后续子节点的 nodeNames 都不同(或者它们是否不同?).. 什么是最嵌套的你能提供的例子吗?

    【讨论】:

    • 不,节点名称是 。页面可以存在于书的内部或外部。一本书可以包含其他书籍或页面。在我上面发布的 XML 中有一个页面有 2 本书的父母。
    【解决方案3】:

    非常感谢 Keith,这就是门票 - 差不多了,我必须做一个小改动,然后它就完美运行了!

    我的代码如下。

    $tocOutput="";
    $.get(tocURL,function(toc){
     function makeToc($xml) {
      // worker function local to makeToc
      function processXml() {
       console.log($(this));
       $tocOutput += "<li><a href='" + $(this).attr("url") + "'>" + $(this).attr("title") + "</a>";
       if (this.nodeName == "BOOK") {
        $tocOutput += "<ul>";
        // recurse on book children
        $(this).children().each(processXml);
        $tocOutput += "</ul>";
       }
       $tocOutput += "</li>";
      }
      // call worker function on all children
      $xml.children().each(processXml);
     }
     var tocOutput = makeToc($(toc));
     $("#toc").html($tocOutput);
     completed($("#toc"));
    });
    

    您会注意到我所做的只是在$.get() 之外声明变量,然后我使用$xml.children().each(processXml); 而不是$(this).find("page").each(processXml); 你有的。

    这样做的原因是孩子可能是页面 OR 书籍,但您所拥有的只是将其限制为页面。

    再次感谢!

    【讨论】:

    • 您可以通过接受我的回答来感谢我!顺便说一句,我的目标不是解决你的整个问题,只是复制你问题中的逻辑。此外,我将变量声明放在 makeToc() 中作为一般的最佳实践。这样做可以清楚地表明,变量只是为了使用 makeToc 来累积结果。
    【解决方案4】:

    此链接提供了一个使用 xml 迭代的好例子 http://anasthecoder.blogspot.in/2012/02/looping-through-xml-with-jquery.html

    xml.find('result').find('permissionDetails').each(function(){
        $(this).children().each(function(){
            var tagName=this.tagName;
            var val=$(this).text();
            if(val==1){
                $('input:checkbox[name='+tagName+']').attr('checked',true);
            }
            else if(val==0){
                $('input:checkbox[name='+tagName+']').removeAttr('checked');
            }
        })
    
    });
    

    【讨论】:

      【解决方案5】:

      这里有一些东西可以赢得更多赞誉。我将其设为匿名函数调用,并使用 arguments.callee 进行递归。我自己也在寻找这种方法,这个和stackoverflow上的另一个线程帮助了我,我想回报它:-)

      $.get(tocURL,function(data){
          var markup = "<ul>";
          $(data).each(function(){
              markup += "<li><a href='" + $(this).attr("url") + "'>" + $(this).attr("title") + "</a>";
              if (this.nodeName == "BOOK") {
                  $markup += "<ul>";
                  $(this).children().each(arguments.callee);    
                  $markup += "</ul>";
              }
              markup += "</li>";
          });
          $("#list").html(markup+"</ul>");
      });
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-11-12
        • 2019-07-07
        • 2013-11-30
        • 1970-01-01
        • 2014-08-02
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多