How can I reorder/sort a NodeList in JavaScript?
Asked Answered
S

3

13

I have what I think should be a straightforward question; let me quickly explain:

In my JavaScript, food.xml is read in with:

getMenuXml.open("GET","food.xml",false);
getMenuXml.send();
xmlDoc=getMenuXml.responseXML;
xmlFoodList = xmlDoc.getElementsByTagName("food");

so that now I have a NodeList xmlFoodList with all the food elements. Great so far. The problem is I want to sort the nodes based on an element <category> inside. I can read that with:

xmlFoodList[i].getElementsByTagName("category")[0].childNodes[0].nodeValue

Later in my code, the food items are displayed in a list, and as you'd expect, I want food of the same category to be listed together. So, my question is: How can I reorder the nodes in xmlFoodList based on their category?

Notes: I can't change food.xml coming in, and I don't want to edit my later code to do the sorting as the list is populated. I don't want to convert the NodeList to an array, since I'd have to rewrite a lot of later code. Performance isn't actually much of a concern, so feel free to clone/nested loop all you want. Thanks for your time.

Shimmy answered 21/1, 2011 at 14:43 Comment(0)
A
16

You can order the elements of the NodeList, if you convert them to an array first:

var foods = xmlDoc.getElementsByTagName("food");
var foodsArray = Array.prototype.slice.call(foods, 0);

Then you can use the sort method:

foodsArray.sort(function(a,b) {
    var aCat = a.getElementsByTagName("category")[0].childNodes[0].nodeValue;
    var bCat = b.getElementsByTagName("category")[0].childNodes[0].nodeValue;
    if (aCat > bCat) return 1;
    if (aCat < bCat) return -1;
    return 0;
});

This is highly dependent on your XML schema though - if, for example, you had foods which were in more than one category they would only be sorted by the first category in the code above.

Aintab answered 21/1, 2011 at 16:31 Comment(4)
I know this is older, but it helped me very much with the issue I was having. Since I had not converted my nodelist into an array, it was not being properly sorted in Chrome. I had a sort function very close to yours, and once I converted it, it worked! Thank you very much!Lanai
When you convert a nodelist into an array, you lose the ability to sort the original elements. For example, let's suppose you wanted to sort an HTML <TABLE> by a particular column. If your nodelist contains the table's rows (tbl.rows), for example, and you sort the nodelist, then the HTML table will also be sorted. But if you convert the nodelist to a standard array and sort the array, then only the data is sorted. Anybody know of a simple way to store a standard array back into a nodelist after a sort?Autopsy
@PaulSwarthout you can order the nodes in the parent element if you do this after sorting: foodsArray.forEach(function(node) { node.parentNode.append(node); });Aintab
@Aintab Yes, that works. But changing a standard array back to a nodelist would let the browser do the node sort itself....which really does exactly what your code does.Autopsy
B
0

Take a look at this: Xml, xsl Javascript sorting. Worst case scenario, you transform the data into precisely the same xml, but sorted. As long as you're paying the transformation penalty, you might consider transforming it into a form more useful for whatever the next step is.

Bassorilievo answered 21/1, 2011 at 14:49 Comment(0)
W
0

It's a good idea to use a Javascript library to get ready-made functions w.r.t Node List operations such as re-ordering, sorting, foreach etc. I would recommend YUI-3, please refer YUI-3 NodeList .

Winchester answered 21/1, 2011 at 15:9 Comment(2)
there is not much about sorting itTrochanter
@ravikirin Please describe in more details, why is it a good idea to pull in "another" library for this? I think it depends on the requirements.Stinger

© 2022 - 2024 — McMap. All rights reserved.