Search code examples
jqueryxmlchildren

JQuery children loop XML


Using JQuery and AJAX, I am getting an XML document and then looping through the document in an attempt to do something at each level of the XML tags/nodes, from parent to children and then children of children respectively.

What i have currently works but is specifically written to a limit of children of children of children (Not ideal).

The final application may have an open ended number of children to do the action to.

How can i make this account for any number of children without the inefficiency?

I have tried making a function with the basis of what i wish to achieve at each child level. But this does not work as expected, essentially breaking the script.

The function

function childX() {
    $(this).children().each(function()
    {
       $("#output").append("<div id='"+(this).nodeName+"'>"+(this).nodeName+"</div><br />");
    });
}

The main script

  $(xml).find("RecentTutorials").children().each(function()
  {

    $("#output").append("<div id='"+(this).nodeName+"'>"+(this).nodeName+"</div><br />");


    $(this).children().each(function()
    {
       $("#output").append("<div id='"+(this).nodeName+"'>"+(this).nodeName+"</div><br />");

      $(this).children().each(function()
        {
           $("#output").append("<div id='"+(this).nodeName+"'>"+(this).nodeName+"</div><br />");

            $(this).children().each(function()
            {
               $("#output").append("<div id='"+(this).nodeName+"'>"+(this).nodeName+"</div><br />");

            });

        });

    });


  //alert((this).nodeName);
  }); 

Solution

  • The easiest way to do this would probably be to use a recursive function - that is, a function that calls itself.

    addChildren( $(xml).find("RecentTutorials") );
    
    function addChildren( $parent ) {
        $parent.children().each( function( i, child ) {
            $("#output").append(
                "<div id='" + child.nodeName + "'>" +
                    child.nodeName +
                "</div><br />"
            );
            addChildren( $(child) );
        });
    }
    

    For an interesting test case, try opening the JavaScript console on any page that uses jQuery - such as the one we are on right now - and paste in this similar code:

    logChildren( $(document.body) );
    
    function logChildren( $parent ) {
        $parent.children().each( function( i, child ) {
            console.log( child.nodeName );
            logChildren( $(child) );
        });
    }
    

    It will print the nodeName for every element in the page.

    BTW I recommend against using this and $(this) when you use jQuery.each(). Instead, use the explicit parameter names as in my examples. It's easier to understand the code this way, and less error-prone too. That is part of the reason your childX() function didn't work at all. It references this in the first line, but when you call a function directly, this is unlikely to be what you expect: unless you're using strict mode, this is a reference to the window object!