2009-10-15 13 views
6

Ich habe einige grundlegenden Code, der einige XML-Code durchlaufen kann, die von Adobe RoboHelp generiert wurde (für unsere Hilfe-Dokumentation). Das funktioniert gut, aber da ein Thema so oft verschachtelt werden kann, wie der Schreiber es möchte, brauche ich einen besseren Weg, um dieses XML zu durchlaufen, als nur Verschachtelungen zu verschachteln.Durchlaufen von XML mit jQuery

Hier ist, was die XML sieht aus wie

<?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> einen Artikel ist, und ein <book> ist ein Ordner.

Her ist mein jQuery-Code, der nur eine Ebene tiefer von Tags aussehen kann

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

ich weiß, gibt es eine bessere Möglichkeit, nur eine Schleife durch alle Elemente und dann bestimmen, ob das Element Kinder, etc., aber ich Ich kann mir einfach nicht vorstellen, wie ich es machen soll.

Jede Hilfe wird sehr geschätzt!

+1

Nur neugierig - warum muss das auf dem Client getan werden? Warum nicht eine XSLT-Transformation auf dem Server anwenden und den HTML-Code senden? Ist das XML dynamisch? Kann der transformierte HTML-Code nicht auf dem Server zwischengespeichert werden? –

+0

Egal, froh, dass Sie eine Lösung gefunden haben - JETZT AKZEPTIEREN KEITHS ANTWORT :) –

+0

Ich ABWEICHE! Dies war nur ein Beweis des Konzepts für jetzt .... eigentlich wollte ich nur einige Leute beeindrucken. Sie duschen mich jetzt mit Lob, also ist es das wert. Irgendwann denke ich, dass wir diese Server-Seite machen werden. –

Antwort

9

Rekursive Funktionen funktionieren gut dafür. Wenn Sie eine Funktion erstellen, die eine interne rekursive Schließung erstellt und verwendet man sie alle auf in einem netten kleinen Paket wickeln kann:

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

können Sie

$(el).children().length verwenden, die zurückkehren würde ‚0‘ oder eine positive Zahl ist, dann Schleife durch, wenn es eine positive Zahl ist, die den Wert true ergibt. Sie könnten auch eine while-Schleife verwenden, um dies rekursiv auszuführen, und den Referenzhandler erneut setzen, aber ich bin mir nicht ganz sicher, ob das funktionieren würde, weil Ihre nodeNames für jedes nachfolgende Kind unterschiedlich sind (oder?) Beispiel, das Sie zur Verfügung stellen können?

+0

Nein, die Knotennamen sind entweder oder . Eine Seite kann innerhalb oder außerhalb eines Buchs existieren. Ein Buch kann andere Bücher oder Seiten enthalten. In der XML, die ich oben gepostet habe, gibt es eine Seite mit 2 Bucheltern. –

1

Vielen Dank Keith, war, dass das Ticket - naja fast, und ich habe machen musste MINOR ändern und dann hat es perfekt funktioniert!

Mein Code ist unten.

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

Sie alle bemerken werde ich tue ist die Variable außerhalb des $.get() deklarieren und dann verwende ich $xml.children().each(processXml); statt $(this).find("page").each(processXml); , die Sie hatten.

Der Grund dafür ist, dass die Kinder Seiten sein könnten OR Bücher, aber was Sie hatten, war es auf nur Seiten zu begrenzen.

Danke nochmal!

+2

Sie können mir danken, indem Sie meine Antwort akzeptieren! Zufälligerweise war es mein Ziel, nicht dein ganzes Problem zu lösen, nur um die Logik in deiner Frage zu kopieren. Außerdem habe ich die Variablendeklaration in makeToc() als allgemeine Best Practice platziert. Auf diese Weise wird deutlich, dass die Variable nur dazu dient, makeToc zum Akkumulieren von Ergebnissen zu verwenden. – keithm

0

Hier ist etwas, um etwas mehr Lob zu verdienen. Ich habe es zu einem anonymen Funktionsaufruf gemacht und die arguments.callee benutzt, um zu rekrutieren. Ich war selbst für diese Methode sucht, und ein anderer Thread bei Stackoverflow hat mir geholfen, und ich will es :-)

zurückzahlen
$.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

Dieser Link ist ein gutes Beispiel für die Verwendung von durch xml Iterieren 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'); 
     } 
    }) 

});