[jQuery] Re: A different approach to parsing XML, and a little help on processing attributes more efficiently
OK got non-standard attributes. It forces one rule, that all non- standard attributes for an element must follow 'id' and 'label'. This is standardized in setting var z=2, as it skips past the first attributes and finds the remaining. Though this is a lot of code for each level of elements; var attribs = $parent[0].attributes attrb=[]; for (var z = 2; z attribs.length; z++) { attrb.push(attribs[z].name +:+ attribs[z].value) } console.log(attrb)
[jQuery] Re: A different approach to parsing XML, and a little help on processing attributes more efficiently
Slick, and super fast. Makes it so that I do not even want to move onto JSON ;-)... (JK, my engineers are forcing me too) Made some minor mods, these add a little time and still processes over 50K lines in about 6-8 seconds, and 100K right about 10 seconds. Now everything is its own html object ready for all the beauty of the rest of jQuery. I wrapped each parent in an ID'ed span and each Location and an ID'ed span. OK this has gone in this direction to the point that I would have to take a different approach to get it better. My other goals are introspecting the XML to determine depth of the PARENT = CHILD relationships. And to pull non-stadard (i.e. not id or label) attributes and manipulate them.
[jQuery] Re: A different approach to parsing XML, and a little help on processing attributes more efficiently
OK this is some progress. Still want more abstraction where I can, though this is much improved. I also need to be able to get arrays of attributes abstractly. function parseXml(xml) { $(xml).find('sites').each(function(){ var PARENTarr = jQuery.makeArray($(this).find('element')); var CHILDarr = jQuery.makeArray($(PARENTarr).find('element')); $.each(PARENTarr, function(i){ var PfromA = $(this); var Pid = $(this).attr(label)+$(this).attr(id); var Cid = $(CHILDarr[i]).attr(label); $(div).append(br/+Pid +br/ + Cid +br/); $(CHILDarr[i]).each(function(){ var CHILDattrs = jQuery.makeArray($(this).find('element')); $(CHILDattrs).each(function(){ var CHILDid = $(this).attr('label') +: + $(this).text(); $(div).append(CHILDid +br/); }); }); }); }); } });
[jQuery] Re: A different approach to parsing XML, and a little help on processing attributes more efficiently
This is better. The arrays are much more efficient, and I cut the code by more than half. I know, I know JSON, I will get there, this is teaching me way more though. I still would like to be able to determine my level of nesting abstractly, and also getting out non- standard attributes. function parseXml(xml) { $(xml).find('sites').each(function(){ var PARENTarr = jQuery.makeArray($(this).find('element')); var CHILDarr = jQuery.makeArray($(PARENTarr).find('element')); $.each(PARENTarr, function(i){ var PfromA = $(this); var Pid = $(this).attr(label)+$(this).attr(id); var Cid = $(CHILDarr[i]).attr(label); $(div).append(br/+Pid +br/ + Cid +br/); $(CHILDarr[i]).each(function(){ var CHILDattrs = jQuery.makeArray($(this).find('element')); $(CHILDattrs).each(function(){ var CHILDid = $(this).attr('label') +: + $(this).text(); $(div).append(CHILDid +br/); }); }); }); }); } });
[jQuery] Re: A different approach to parsing XML, and a little help on processing attributes more efficiently
This is better. The arrays are much more efficient, and I cut the code by more than half. I know, I know JSON, I will get there, this is teaching me way more though. I still would like to be able to determine my level of nesting abstractly, and also getting out non- standard attributes. BTW processed over 50K lines in ~5seconds no errors. function parseXml(xml) { $(xml).find('sites').each(function(){ var PARENTarr = jQuery.makeArray($(this).find ('element')); var CHILDarr = jQuery.makeArray($(PARENTarr).find ('element')); $.each(PARENTarr, function(i){ var PfromA = $(this); var Pid = $(this).attr (label)+$(this).attr(id); var Cid = $(CHILDarr [i]).attr(label); $(div).append(br/ +Pid +br/ + Cid +br/); $(CHILDarr[i]).each (function(){ var CHILDattrs = jQuery.makeArray($(this).find('element')); $ (CHILDattrs).each(function(){ var CHILDid = $(this).attr('label') +: + $(this).text(); $ (div).append(CHILDid +br/); }); }); }); }); }
[jQuery] Re: A different approach to parsing XML, and a little help on processing attributes more efficiently
Let's me have multiple children: function parseXml(xml) { $(xml).find('sites').each(function(){ var PARENTarr = jQuery.makeArray($(this).find('element')); $(PARENTarr).each(function(i){ $(div).append(br/+ $(this).attr(label)+(i+1) +br/); var CHILDarr = jQuery.makeArray($(PARENTarr[i]).find ('element')); $(CHILDarr).each(function(p){ $(div).append($(this).attr(label) +br/); var CHILDattrs = jQuery.makeArray($(CHILDarr[p]).find ('element')); $(CHILDattrs).each(function(){ var CHILDid = $(this).attr('label') +: + $(this).text(); $(div).append(CHILDid +br/); p=0; }); }); }); }); } });
Re: [jQuery] Re: A different approach to parsing XML, and a little help on processing attributes more efficiently
No worries on the XML vs. JSON. It's been interesting to watch your progress in refactoring the code. I hope it's useful for other people too. A few notes on the latest version... * Avoid using ALLCAPS or PARTIALcaps in a variable name. Many JavaScript programmers will think you intend such variables to be used as constants. (That is, a variable whose content is not intended to be changed.) * You don't need all those makeArray calls. * It's a bit confusing to mix the use of $ and jQuery in the same code. Use one or the other consistently. * Stop appending to $('div') Very bad habit! What happens when you add another DIV to your page? Use a $('#container') selector instead. * Even though you're still doing XML parsing, you will get much faster performance by building an HTML string, and make sure the entire HTML content is enclosed in one wrapper DIV. * Watch out for all the duplicate $(something) selectors. If you use the same $(something) more than once, than do this instead: var $something = $(something); $something.whatever(); // instead of $(something).whatever(); Putting those tips together, you get something like this: function parseXml( xml ) { var html = []; html.push( 'div' ); $(xml).find('sites').each( function() { $(this).find('element').each( function( i, parent ) { var $parent = $(parent); html.push( 'br/', $parent.attr('label'), i + 1, 'br/' ); $parent.find('element').each( function( j, child ) { var $child = $(child); html.push( $child.attr('label'), 'br/' ); $child.find('element').each( function( k, inner ) { var $inner = $(inner); html.push( $inner.attr('label'), ': ', $inner.text(), 'br/' ); }); }); }); }); html.push( '/div' ); $('#container').append( html.join('') ); } -Mike On Tue, Feb 2, 2010 at 4:10 PM, augur 312...@gmail.com wrote: function parseXml(xml) { $(xml).find('sites').each(function(){ var PARENTarr = jQuery.makeArray($(this).find('element')); $(PARENTarr).each(function(i){ $(div).append(br/+ $(this).attr(label)+(i+1) +br/); var CHILDarr = jQuery.makeArray($(PARENTarr[i]).find ('element')); $(CHILDarr).each(function(p){ $(div).append($(this).attr(label) +br/); var CHILDattrs = jQuery.makeArray($(CHILDarr[p]).find ('element')); $(CHILDattrs).each(function(){ var CHILDid = $(this).attr('label') +: + $(this).text(); $(div).append(CHILDid +br/); p=0; }); }); }); }); } });
[jQuery] Re: A different approach to parsing XML, and a little help on processing attributes more efficiently
I was headed in this direction I was trying to get to the function (i,parent),function(j,child) I had not quite figured that part out which is obvious. Let's see what this does. Thanks Chad
[jQuery] Re: A different approach to parsing XML, and a little help on processing attributes more efficiently
That is really nice. 100K lines really fast no script time outs. I need to get back and study a little more. I was so terribly close, but missed some really basic principles.
[jQuery] Re: A different approach to parsing XML, and a little help on processing attributes more efficiently
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.
Re: [jQuery] Re: A different approach to parsing XML, and a little help on processing attributes more efficiently
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 312...@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.
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 m...@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 312...@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.
[jQuery] Re: A different approach to parsing XML, and a little help on processing attributes more efficiently
Small Tweaks, less lines of code. Still no major breaks in breaking the nested model for XML parsing. Things that I am interested in are being able to determine levels of nesting abstractly, being able to determine attributes abstractly, being able to hold results in an Array, build the array, and then append the array. function parseXml(xml) { $(xml).find('sites').each(function(){ $(this).find('element').each(function(){ var PARENT = $(this); var siteBLOCK = $(div).append(PARENT.attr(label) +' '+ PARENT.attr(id) + br/ ); $(PARENT).find('element').each(function(){ var THISis = $(this); siteBLOCK = $(div).append(THISis.attr('label') +: Has a latitude of + PARENT.attr('lat') + and a longitude of + PARENT.attr ('lng') + br/ ); $(THISis).find('element').each(function(){ var thisCHILD = $(this); siteBLOCK = $(div).append(thisCHILD.attr('label') +: + thisCHILD.text() + br/); }); }); }); }); } });
[jQuery] Re: A different approach to parsing XML, and a little help on processing attributes more efficiently
This gets the variables at the top level and gives me the correct count for each level. function parseXml(xml) { $(xml).find('sites').each(function(){ var PARENT = $(this).children($(this).attr('id')); var PARENTcount = PARENT.length; var PARENTSchildren = $(PARENT).children($(this).attr('label')); var CHILDRENcount = PARENTSchildren.length; var CHILDSchildren = $(PARENTSchildren).children($(this).attr ('label')); var CHILDScount = CHILDSchildren.length; alert(PARENTcount) alert(CHILDRENcount) alert(CHILDScount) }); }
[jQuery] Re: A different approach to parsing XML, and a little help on processing attributes more efficiently
Now I am treating each order of elements separately as their own objects. This is much faster, if I can figure out how to append the results correctly. function parseXml(xml) { $(xml).find('sites').each(function(){ PARENT = $(this); var PARENTarr = jQuery.makeArray($(this).children($(this).attr ('id'))); var CHILDRENarr = jQuery.makeArray($(PARENTarr).children($(this).attr ('label'))); var CHILDSarr = jQuery.makeArray($(CHILDRENarr).children($(this).attr ('label'))); alert (PARENTarr.length + + CHILDRENarr.length + + CHILDSarr.length); var PARENTobjs = {thisPARENT: $(PARENTarr).each(function(i){ var PARENTid = $(PARENTarr[i]).attr('id'); alert(PARENTid); }) } var CHILDRENobjs = {thisCHILDREN: $(CHILDRENarr).each(function(n){ var CHILDRENlabel = $(CHILDRENarr[n]).attr('label'); alert(CHILDRENlabel); }) } var CHILDSobjs = {thisCHILD:$(CHILDSarr).each(function(p){ var CHILDSlabel = $(CHILDSarr[p]).attr('label'); var CHILDStext = $(CHILDSarr[p]).text(); alert(CHILDSlabel + : + CHILDStext); }) } }); }
[jQuery] Re: A different approach to parsing XML, and a little help on processing attributes more efficiently
this treats processes each order of element separately as a variable. If I can append these correctly. I think that this might be a slightly better process. It is at least treating things in a more object oriented manner. $(xml).find('sites').each(function(){ PARENT = $(this); var PARENTarr = jQuery.makeArray($(this).children($(this).attr ('id'))); var CHILDRENarr = jQuery.makeArray($(PARENTarr).children($(this).attr ('label'))); var CHILDSarr = jQuery.makeArray($(CHILDRENarr).children($(this).attr ('label'))); var PARENTobjs = {thisPARENT: $(PARENTarr).each(function(i){ var PARENTid = $(PARENTarr[i]).attr('id'); alert(PARENTid); }) } var CHILDRENobjs = {thisCHILDREN: $(CHILDRENarr).each(function(n){ var CHILDRENlabel = $(CHILDRENarr[n]).attr('label'); alert(CHILDRENlabel); }) } var CHILDSobjs = {thisCHILD: $(CHILDSarr).each(function(p){ var CHILDSlabel = $(CHILDSarr[p]).attr('label'); var CHILDStext = $(CHILDSarr[p]).text(); alert(CHILDSlabel + : + CHILDStext); }) } }); }
[jQuery] Re: A different approach to parsing XML, and a little help on processing attributes more efficiently
Funny thing is, my lead engineer said the same thing... Mostly this was an experiment to gain a better understanding of DOM outside of HTML. This is about as exciting as a SAX parser when it comes to speed (5sec in safari for 20K lines, slightly longer in FireFox, and noticeably longer in Chrome), though it is fairly efficient, and gives me exactly the results I was wanting to see. There are some practical applications. Realizing that there is only so much memory out there more efficiency is what I am going for, so any input on this script is helpful. I have approached it this way because I get XML and DOM, and I am getting decent at jQuery. Thus this method was in my range of current understanding. JSON is something that I am just now becoming more familiar with.
Re: [jQuery] Re: A different approach to parsing XML, and a little help on processing attributes more efficiently
No offense, but that code is really frightening. Not your fault though. JSON is not only much faster than all this XML/DOM garbage, but it is *much* easier to understand and use too! If you're coding JavaScript, you need to know how to use ordinary JavaScript objects and arrays, yes? If you know how to work with those, then you *already know JSON*. Because JSON is just JavaScript objects. (D'oh! JavaScript Object Notation!) So here's your XML file transcribed fairly faithfully into JSON: { sites: [ { label: site, id: 2, lat: 27, lng: 305, location: { city: Las Vegas, state: NV, region: West } }, { label: site, id: 3, lat: 106, lng: 35, location: { city: Pittsburgh, state: Penn, region: North East } } ] } I only included a couple of the entries to keep the example short. As you can see, that's just a JavaScript object. This JavaScript object contains a single property called 'sites'. That property is an array of objects, each one representing a single site. Those site objects have the same properties as your XML file. So here's how you use it. I didn't try to exactly duplicate what your code is doing - I wasn't sure what it was trying to do with all the $('div') calls. Wouldn't those append to every DIV in your page? Oh - is there only a single DIV that you're appending everything to? You should give it an ID and reference it that way instead. Also I realized I didn't quite duplicate what you're doing with those label=Location elements. It looks like you might have other kinds of label=Something elements as well? I didn't notice that, but tell you what, here's the code as I understood it: $.getJSON( 'sites.json', function( json ) { var html = []; html.push( 'div' ); var sites = json.sites; for( var site, i = -1; site = sites[++i]; ) { var location = site.location; html.push( site.label, ' ', site.id, 'br/', 'Lat: ', site.lat, ' Lng: ', site.lng, 'br/', location.city, ', ', location.state, 'br/', location.region ); } html.push( '/div' ); $('#container').html( html.join('') ); }); As you can see, that is many times simpler - and *much* easier to understand - than the XML parsing. Some other speed notes... * The for loop uses a slightly unusual form that is faster than the usual numeric incrementing. * Instead of appending elements to the HTML DOM as we go, we construct a single HTML string and append it in one operation. * That HTML string has an outermost DIV that wraps all the elements inside it. * We construct the HTML string not with += but by pushing the elements onto an array and joining it at the end. There is actually a way to speed this up a slight bit more in IE, but let's leave that for the next installment. :-) As it is now, this code will be many times faster than the XML code - at least one order of magnitude faster, and maybe two. Let me know what the real deal is with those label=location elements and I can suggest how to handle them. -Mike On Thu, Jan 28, 2010 at 11:31 AM, augur 312...@gmail.com wrote: Funny thing is, my lead engineer said the same thing... Mostly this was an experiment to gain a better understanding of DOM outside of HTML. This is about as exciting as a SAX parser when it comes to speed (5sec in safari for 20K lines, slightly longer in FireFox, and noticeably longer in Chrome), though it is fairly efficient, and gives me exactly the results I was wanting to see. There are some practical applications. Realizing that there is only so much memory out there more efficiency is what I am going for, so any input on this script is helpful. I have approached it this way because I get XML and DOM, and I am getting decent at jQuery. Thus this method was in my range of current understanding. JSON is something that I am just now becoming more familiar with.
[jQuery] Re: A different approach to parsing XML, and a little help on processing attributes more efficiently
Mike, Thanks so much for taking the time for writing this tutorial. I see how this is effective. I attempted to do similar things with the XML however... The Data Objects for JSON are much more simplistic structurally, and a little obtuse for reading visually. As I mentioned this simply is a model that I am working on to traverse XML. The content is not important. That I am able to traverse it is important. In a real world application of this I would be working from an XML delivery. It does not really make too much sense to convert the XML into JSON, though it may make sense to have JSON be an output method for the mechanism delivering the info (something to consider) I will look into using an array for building the output, since I am passing the parent=child variables I should be able to appendTo (div) when I am done now. In a more complex layout I would worry about ID, but for now since there is only one I do not need to worry about it. The Location node was created to add a level of relationship to be traversed. You could look at it as a product with variations, there are Product attributes and Variant attributes all wrapped up in one little bundle. Definitely not a mapping app that I am working on, just the structure lent itself to my test, and also a number of tutorials seems to use locational info. I think that this XML parser could be more efficient in two ways. First in traverse methodology, there has to be some way to declare objects at the top and then process them. Additionally abstracting the process for setting attributes as variables is a place this could get better.