Jump to content

Parsing XML


johnnyg24

Recommended Posts

I have an XML document that looks like the following:

<records><record><image>ACES-6</image><red>27 </red><green>29 </green><blue>30 </blue></record>etc...</records>

I have about 2000 <record>. The XML is designed to store RGB colors of the <image>. The user is submitting their own RGB colors and I am comparing them to the XML list of RGB as follows:

var r1 = $('#userRed').val()	var g1 = $('#userGreen').val()	var b1 = $('#userBlue').val()	var colorArray = new Array()	var range = 10		var threshold = 5//colors is the xml	$(colors).find('record').each(function(){										 		var r2 = $(this).find('red').text()		var g2 = $(this).find('green').text()		var b2 = $(this).find('blue').text()				if(Math.abs(r1-r2)<range){			if(Math.abs(g1-g2)<range){				if(Math.abs(b1-b2)<range){					var diff = (Math.abs(r1-r2)*.3) + (Math.abs(g1-g2)*.59) + (Math.abs(b1-b2)*.11)					if(diff<threshhold){						colorArray.push(diff+":"+$(this).find('image').text())					}									}			}		}	})

I then display the images that meet the user color request. My problem is going through the XML takes awhile. As you can see if the red color is not within my range, then it is ignored and it moves to the next <record>. But I am still going through the entire XML document. Is there a way to select only the <record> where the <red> is with in my range or will I always have to parse through the entire XML?

Link to comment
Share on other sites

maybe you could use a return statement to end the script when the color is found?

Link to comment
Share on other sites

Wouldn't I have to still parse through the entire XML? I think that because RGB colors range from 0 to 255 I could set up my XMl as follows:

<colors><color> <record>  <image></image>  <green></green>  <blue></blue> </record> <record>  <image></image>  <green></green>  <blue></blue> </record></color><color> <record>  <image></image>  <green></green>  <blue></blue> </record></color></colors>

This would allow me to create 255 <color> tags, each containing a number of <record> where the <red> value would correspond to the index number of <color>. This way I can find my range of red by indexing the XML and gather my set of <record> values.

Link to comment
Share on other sites

If you use JQuery's each() method, then yes, you'll have to pass over every node. If you instead loop "manually" over the collection, you can put a "break;" winthin the loop, and therefore end it prematurely.To put it in code, replace:

	$(colors).find('record').each(function(){										 		var r2 = $(this).find('red').text()		var g2 = $(this).find('green').text()		var b2 = $(this).find('blue').text()				if(Math.abs(r1-r2)<range){			if(Math.abs(g1-g2)<range){				if(Math.abs(b1-b2)<range){					var diff = (Math.abs(r1-r2)*.3) + (Math.abs(g1-g2)*.59) + (Math.abs(b1-b2)*.11)					if(diff<threshhold){						colorArray.push(diff+":"+$(this).find('image').text())					}									}			}		}	})

with something like

	var records = $(colors).find('record');	for(var i=0; i<records.length; i++) {										 		var r2 = $(this).find('red').text();		var g2 = $(this).find('green').text();		var b2 = $(this).find('blue').text();				if(Math.abs(r1-r2)<range){			if(Math.abs(g1-g2)<range){				if(Math.abs(b1-b2)<range){					var diff = (Math.abs(r1-r2)*.3) + (Math.abs(g1-g2)*.59) + (Math.abs(b1-b2)*.11)					if(diff<threshhold){						colorArray.push(diff+":"+$(this).find('image').text());						break;//Assuming that's the point after which you want to terminate the whole loop					}									}			}		}	}

Link to comment
Share on other sites

I see what you are saying. The script is meant to gather a collection of images, I think if I have the break after the pushing the first match, then the loop will stop and I will always have just one result. Or I am not reading your recommendation correctly?

Link to comment
Share on other sites

I see what you are saying. The script is meant to gather a collection of images, I think if I have the break after the pushing the first match, then the loop will stop and I will always have just one result. Or I am not reading your recommendation correctly?
Yes. You are reding it correctly. I'm not sure if you get the length of the collection with object.length, but the point stands...If you want to get the first N matches instead, you'll have to keep a counter within a separate variable, and terminate the loop when the counter reaches N.
Link to comment
Share on other sites

Under that scenario you would still be going through the entire XML document until you reached the end. I'm trying to avoid having to look at every record to determine if it will pass my test. I think reworking the structure of the XML is the best approach. For example, if I know that the red value has to be 100 and if I keep all the images with a red value in the 100th <color> tag, then all I have to do is index to color[100] and then run my tests on just those results. I will have ignored the other 254 <color> tags and therefore ignored all the images that will never pass the initial red value test.

Link to comment
Share on other sites

Under that scenario you would still be going through the entire XML document until you reached the end. I'm trying to avoid having to look at every record to determine if it will pass my test. I think reworking the structure of the XML is the best approach. For example, if I know that the red value has to be 100 and if I keep all the images with a red value in the 100th <color> tag, then all I have to do is index to color[100] and then run my tests on just those results. I will have ignored the other 254 <color> tags and therefore ignored all the images that will never pass the initial red value test.
What scenario? The first N matches? No, you'll only have to look at every node until you reach the N amount (and you'll find if you're at the N-th match using the counter). You can then break, and therefore stop traversing other nodes.If you want to find all matches, then yes, you'll have to traverse the whole collection. But if you want all matches, then you should probably use jQuery's methods. I think it had a filter() or something, whereby it returns a collection of all collection elements that match the criteria.
Link to comment
Share on other sites

I'll look into the filter(), I've never used it before. I guess the bottom line is to avoid having to filter though every record to find all that match, a more efficient way would to know exactly were to look based on indexing. If I'm looking for every image with the red value = 100, then I should have a tag containing all the images, with a red value = 100, at index[99] (based on the index starting at 0). Then use my filter to weed out any of those images, at index[99], that don't pass the rest of my test.

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...