AS3: Inserting XML Elements Alphabetically By A Property
So I'm having a slightly tricky issue...
I'm generating an XML file within a class I'm writing. Let's say this was the starting XML:
<base>
<container id="0">
<element type="Image" x="0" y"0" />
<element type="Image" x="100" y"0" />
<container/>
</base>
I want to add additional <element>
's. The first order of sorting is by "type", then "x", then "y". So if I add a new "type" of <element>
, let's say type "Text", I want Text to be inserted after any "Image" <element>
's.
For example:
<base>
<container id="0">
<element type="Image" x="0" y"0" />
<element type="Image" x="100" y"0" /&开发者_运维问答gt;
<element type="Text" x="200" y"100" />
<container/>
</base>
The basic idea is to keep the list sorted as I add more <element>
's to each <container>
... The numeric sorting is simple enough, but I can't figure out a clean way to sort alphabetically.
Suggestions are appreciated.
The only thing I can think of is to get the types into an Array. Add the "new type", sort and call indexOf()... the number SHOULD be the current position I should insert before? Feels kludgy.
I would suggest reading all the existing XML elements into an array, adding your new elements, sorting the array, then writing every element back out. This might be easier than trying to figure out which index each new element should be inserted at. This may not be very efficient, though, depending on your situation.
For doing the sorting, I would try something like this (untested):
array.sort(function (a:XML, b:XML) {
if (a.@type < b.@type) return -1;
if (a.@type > b.@type) return +1;
if (Number(a.@x) != Number(b.@x)) return Number(a.@x) - Number(b.@x);
return Number(a.@y) - Number(b.@y);
});
EDIT: Added casts in the sort compare function.
Can you change the XML structure? You could wrap all Image elements in an <images>
node, Text elements in a <texts>
node and so forth, and this way adding elements to the right place would be easy.
You could still get all the <element>
nodes by accessing base.container.*.element
.
tested... assuming you have valid XML, and you create a variable for the sorted XML with a the same root child as the original XML. Mine just happened to be devices.
var sortedXML:XML = <devices></devices>;
function sortBy(xmlFile:XML , field:String, order:int)
{
// array that will hold index of nodes
var arr:Array = new Array();
// loop through nodes
for each (var someNode:XML in xmlFile.*)
{
// array gets populated with node that matches 'field'
arr.push(someNode.child(field));
}
// sort the 'arr' array alphabetically
arr.sort();
// reverse the alphabetical order if necessary
if (order == -1)
{
arr.reverse();
}
// append the nodes in from the source, in the order of the array
for (var i:int=0; i<arr.length; i++)
{
sortedXML.appendChild(myXML.device.(child(field) == arr[i]));
}
}
// trace your original xml then trace sortedXML to verify
精彩评论