开发者

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
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜