如何在JavaScript中重新排序/排序NodeList?

13

我认为这应该是一个简单明了的问题,让我快速解释一下:

在我的JavaScript中,使用以下代码将food.xml读入:

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

现在我有一个包含所有食品元素的NodeList xmlFoodList。到目前为止都很好。问题是我想根据<category>元素内部的内容对节点进行排序。我可以使用以下代码读取该元素:

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

在我的代码后面,食品项目以列表形式显示,正如你所期望的那样,我希望相同类别的食品被列在一起。因此,我的问题是:如何根据它们的类别重新排序xmlFoodList中的节点?

注:我无法更改传入的food.xml,也不想编辑稍后的代码以在填充列表时进行排序。我不想将NodeList转换为数组,因为我需要重写很多后续代码。实际上性能并不是太大的问题,因此可以自由地克隆/嵌套循环。感谢您的时间。

3个回答

16
你可以先将NodeList转换为数组,然后对其元素进行排序:
var foods = xmlDoc.getElementsByTagName("food");
var foodsArray = Array.prototype.slice.call(foods, 0);

那么您可以使用 sort 方法:

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;
});
这在很大程度上取决于你的XML模式 - 例如,如果某些食品属于多个类别,则它们只会按照代码中的第一个类别进行排序。

我知道这篇文章比较旧,但它对我解决问题非常有帮助。由于我没有将我的节点列表转换为数组,在Chrome浏览器中无法正确排序。我的排序函数与你的非常接近,一旦我进行了转换,它就可以正常工作了!非常感谢! - illinoistim
当您将节点列表转换为数组时,您会失去对原始元素进行排序的能力。例如,假设您想按特定列对HTML <TABLE>进行排序。如果您的节点列表包含表格行(tbl.rows),并且您对节点列表进行排序,则HTML表格也将被排序。但是,如果您将节点列表转换为标准数组并对数组进行排序,则仅数据会被排序。有人知道一种简单的方法可以在排序后将标准数组存储回节点列表中吗? - Paul Swarthout
1
@PaulSwarthout 如果你在排序后这样做,就可以按父元素中的节点顺序排列: foodsArray.forEach(function(node) { node.parentNode.append(node); }); - andrewmu
@andrewmu 是的,那样可以。但是将标准数组更改回节点列表会让浏览器自己进行节点排序...这实际上就是您的代码所做的事情。 - Paul Swarthout

1

使用JavaScript库来获取关于Node List操作的现成函数,如重新排序、排序、foreach等,是一个好主意。我建议使用YUI-3,请参考YUI-3 NodeList


关于排序的内容不多。 - lisak
@ravikirin请详细描述一下,为什么引入“另一个”库是个好主意?我认为这取决于需求。 - Adrian

0

看看这个:Xml,xsl Javascript sorting。最坏的情况是,您将数据转换为完全相同的已排序xml。只要您支付了转换成本,您可以考虑将其转换为更适合下一步操作的形式。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接