2009-10-15 6 views
6

私は、Adobe RoboHelp(ヘルプドキュメント用)から生成されたXMLをループする基本的なコードをいくつか持っています。これはうまくいきますが、作者が望むようにトピックを入れ子にすることができるので、ループを入れ子にするのではなく、このXMLをループするより良い方法が必要です。.each()ここでjQueryでXMLをループする

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

A <page>どのように見えるかの記事で、<book>はフォルダです。

彼女はなどタグのみ

//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); 

の深い1つのレベルを見ることができます私のjQueryのコード、私はすべての要素を通してだけループする良い方法があります知っているし、その後の要素が子を持つかどうかを判断、だけどそれをどうやって行うのか考えることはできません。

ご協力いただきありがとうございます。

+1

ちょっと好奇心 - なぜこれをクライアントで行う必要がありますか?なぜサーバー上でXSLT変換を適用せずにHTMLを送信するのですか? xmlは動的ですか?変換されたhtmlはサーバーにキャッシュされませんか? –

+0

それにもかかわらず、あなたが解決策を見つけられてうれしく思いました - 今すぐキーの答えを受け入れます:) –

+0

私は拒否します!これは今のところコンセプトの証明に過ぎませんでした....実際に私はただの人々に印象づけたかっただけです。彼らは今私に賞賛を浴びせているので、それは価値がある。結局私はこのサーバー側をやっていると思う。 –

答えて

9

これには再帰関数が適しています。あなたは小ぎれいなパッケージにすべてを包むことができ、内部再帰的な閉鎖を作成し、使用する関数を作成する場合:

$.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); 
}); 
1

あなたはそれがtrueと評価され、正の数だ場合はループスルー、その後、「0」または正の数を返します

$(el).children().lengthを使用することができます。 whileループを使用して再帰的に行うこともできますが、参照ハンドラを再設定することもできますが、後続の各子のnodeNamesが異なる(またはそれらのノード名が異なるために)うまくいくとは思えません。あなたが提供できる例は?

+0

いいえ、ノード名はまたはです。ページは本の中または外に存在することができます。書籍には他の書籍やページを含めることができます。 上記のXMLには、2つの本の親を持つページがあります。 –

1

本当にありがとうございましたキース、それは切符だった - だけでなく、ほとんど、私は1つをしなければなりませんでしたMINORの変更は完全に機能しました!

私のコードは以下の通りです。

$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); を使用しています。

この理由は、子どもがページまたはの書籍になる可能性がありますが、あなたが持っていたのはページだけに限定されていたからです。

もう一度おねがいします!

+2

あなたは私の答えを受け入れることによって私に感謝することができます!ちなみに、私の目標はあなたの問題全体を解決することではなく、あなたの質問のロジックを複製することでした。また、一般的なベストプラクティスとして、変数宣言をmakeToc()内に配置しました。このようにすると、makeTocを使用して結果を累積するためだけに変数が使用されることが明らかになります。 – keithm

0

ここにいくつかの賞賛を得るために何かがあります。私はそれに無名関数呼び出しを行い、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>"); 
}); 
1

このリンクは、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'); 
     } 
    }) 

});