Tuesday, February 2, 2010

Re: [jQuery] Re: A different approach to parsing XML, and a little help on processing attributes more efficiently

I don't know why Google Groups keeps inserting those semi-random blank lines in the code! Now I'm curious, so I'm trying something a bit different - let's see what happens..

function parseXml( xml ) {
    var html = [];
    html.push( '<div>' );
    $(xml).find('sites').$each( function( $site ) {
        $site.find('>element').$each( function( $parent, i ) {
            html.push( '<br/>', $parent.attr('label'), i + 1, '<br/>' );
            $parent.find('>element').$each( function( $child ) {
                html.push( $child.attr('label'), '<br/>' );
                $child.find('>element').$each( function( $inner ) {
                    html.push( $inner.attr('label'), ': ', $inner.text(), '<br/>' );
                });
            });
        });
    });
    html.push( '</div>' );
  
    $('#container').append( html.join('') );
}


On Tue, Feb 2, 2010 at 10:54 PM, Michael Geary <mg@mg.to> wrote:
Cool, it will be good to see your continued work. We may be among the last holdouts in this mailing list - but I figure since the thread started here we can carry on.

BTW you may notice one bit of annoying repeated boilerplate in that last version. See how the callback functions for all the .each() loops begin with something like:

    var $foobar = $(foobar);

Why don't we extend jQuery with a better version of .each() that does that for us?

Let's call it .$each() as a reminder that it gives the callback a DOM element that's already been wrapped with a $(). It would look like this:

jQuery.fn.$each = function( callback ) {
    for( var element, i = -1;  element = this[++i]; )
        callback( jQuery(element), i );
};

Note that in addition to calling jQuery(element), it also reverses the callback arguments - in most cases you only need the element inside the callback - it's much less often that you need the index. (In your code, only one of the four loops uses the index.)

So, using that function, the code can be written as:


function parseXml( xml ) {
    var html = [];
    html.push( '<div>' );
    $(xml).find('sites').$each( function( $site ) {
        $site.find('>element').$each( function( $parent, i ) {

            html.push( '<br/>', $parent.attr('label'), i + 1, '<br/>' );
            $parent.find('>element').$each( function( $child ) {

                html.push( $child.attr('label'), '<br/>' );
                $child.find('>element').$each( function( $inner ) {

                    html.push( $inner.attr('label'), ': ', $inner.text(), '<br/>' );
                });
            });
        });
    });
    html.push( '</div>' );
   
    $('#container').append( html.join('') );
}

That's getting pretty clean!

Note that the code still uses the naming convention of $foobar for a jQuery object - it helps make it clear which variables are jQuery objects.

-Mike


On Tue, Feb 2, 2010 at 10:27 PM, augur <312624@gmail.com> wrote:
OK, so this is much better than a lesson in parsing XML. Showing the
errors that I had made in my process, you have also shown sound jQuery
which I was having a hard time picking up from the documentation. I
tend to learn best by doing and getting feedback. Mike, thank you. I
am going to keep this chain going with my mods as I make them.


No comments: