Вместо этого рассмотрим следующий подход:
script.jsx
/**
* Extend Array prototype to have a indexOf function
*/
Array.prototype.indexOf = function(item) {
var index = 0, length = this.length;
for ( ; index < length; index++ ) {
if ( this[index] == item )
return index;
}
return -1;
};
var xmlString = '\
<films>\
<film name="Foobar" version="2D"></film>\
<film name="Foobar" version="3D"></film>\
<film name="Foobaz" version="2D"></film>\
<film name="Foobaz" version="3D"></film>\
<film name="Foo" version="3D"></film>\
<film name="Quux" version="2D"></film>\
<film name="Quux" version="3D"></film>\
</films>';
var xml = new XML(xmlString);
var sortVersion = ['2D', '3D'];
// 1. Create a temporary XML object with a matching `films` root element.
var tempXml = new XML('<' + xml.name() + '></' + xml.name() + '>');
for (var index = 0, max = xml.elements().length(); index < max; index++) {
// Fetch meta data of previous movie
var prevTitle = String(xml.elements()[index - 1].@name);
var prevVersion = xml.elements()[index - 1].@version;
var prevVersionIdx = sortVersion.indexOf(prevVersion);
// Fetch meta data of current movie
var curTitle = String(xml.elements()[index].@name);
var curVersion = xml.elements()[index].@version;
var curVersionIdx = sortVersion.indexOf(curVersion);
// 2. Insert each XML element node from the original XML Object into
// the temporary XML Object and position (i.e. sort) as neccessary.
if (prevTitle === curTitle && prevVersion < curVersion) {
tempXml.insertChildBefore(tempXml.elements()[index -1], xml.elements()[index])
} else {
// There's nothing to change (i.e. sort) so insert it as-is .
tempXml.insertChildBefore(tempXml.elements()[index], xml.elements()[index])
}
}
// 3. Overwrite original XML object's children with temporary (sorted) XML objects children.
xml.setChildren(tempXml.children());
// 4. Delete temporary XML object.
tempXml = undefined;
// Testing...
$.writeln(xml)
$.writeln('-----------------')
$.writeln(xml.elements().length())
$.writeln('-----------------')
Пояснение:
Вместо того, чтобы пытаться манипулировать (т.е. сортировать) исходным XML-объектом, приведенная выше суть делает следующее:
Создает другой объект XML, который содержит только корневой элемент <films>
. Этот объект XML будет временным.
Во время каждого хода цикла for
мы;
- Вставьте клон каждого узла элемента XML из исходного объекта XML во временный объект XML.
- Позиция (т.е. сортировка) каждого узла элемента XML по мере необходимости.
Перезаписать исходные узлы дочерних элементов объектов XML узлами дочерних элементов из временного / отсортированного объекта XML.
Наконец, мы удаляем временный объект XML (т.е. устанавливаем его на undefined
), поскольку он больше не требуется.
Результат
Приведенный выше пример включает в себя следующий исходный XML:
<films>
<film name="Foobar" version="2D"></film>
<film name="Foobar" version="3D"></film>
<film name="Foobaz" version="2D"></film>
<film name="Foobaz" version="3D"></film>
<film name="Foo" version="3D"></film>
<film name="Quux" version="2D"></film>
<film name="Quux" version="3D"></film>
</films>
, который будет преобразован в следующее:
<films>
<film name="Foobar" version="3D"/>
<film name="Foobar" version="2D"/>
<film name="Foobaz" version="3D"/>
<film name="Foobaz" version="2D"/>
<film name="Foo" version="3D"/>
<film name="Quux" version="3D"/>
<film name="Quux" version="2D"/>
</films>
Примечание: Для более сложных структур XML и требований к преобразованию, чем в примере, приведенном в вашем вопросе, я бы подумал об использовании XSLT . Учитывая ваше текущее требование, шаблон типа этот достигнет желаемого результата.