Как обновить дочерний элемент XML-документа независимо от его «вертикального индекса» / глубины в actionscript 3? - PullRequest
0 голосов
/ 23 декабря 2009

Я нахожусь в ситуации, когда у меня есть документ xml, который будет обновлен следующим образом: Самый глубокий дочерний элемент в документе, который окружает определенную позицию x, y (в зависимости от его x, y, ширины и Атрибуты высоты) собирается получить новый дочерний элемент. Если существует несколько дочерних объектов с одинаковой глубиной, обновляется нижний.

Моим первым шагом было найти этого самого глубокого ребенка, это уже вызывало проблемы, но мне удалось решить эту проблему с помощью следующей рекурсии:

//returns the deepest element which surrounds the given position
        private static function getDeepestElementAtPos(curElement:XML, depth:uint, targetX:uint, targetY:uint, totParentX:uint = 0, totParentY:uint = 0):Object
        {
            var deepestElement:Object = new Object();
            deepestElement["xml"] = curElement;
            deepestElement["depth"] = depth;

            var posDeeperChild:Object;
            for each (var child:XML in curElement.children())
            {
                if (posInsideNode(child, totParentX, totParentY, targetX, targetY))
                {
                    posDeeperChild = getDeepestElementAtPos(child, depth + 1, targetX, targetY, totParentX + Number(child.@x), totParentY + Number(child.@y));
                    if (posDeeperChild["depth"] > depth) deepestElement = posDeeperChild;
                }
            }

            return deepestElement;
        }

        //returns whether the given position is inside the node
        private static function posInsideNode(child:XML, offsetX:uint, offsetY:uint, targetX:uint, targetY:uint):Boolean
        {
            //if all required properties are given for an element with content
            if ((child.@x.length() == 1) && (child.@y.length() == 1) && (child.@width.length() == 1) && (child.@height.length() == 1))
            {
                //if the new object is inside this child
                if ((Number(child.@x) + offsetX <= targetX) && (Number(child.@x) + offsetX + Number(child.@width) >= targetX) && (Number(child.@y) + offsetY <= targetY) && (Number(child.@y) + offsetY + Number(child.@height) >= targetY))
                {
                    return true;
                }
            }
            return false;
        }

Теперь, следующий шаг - обновить полный код обновленным потомком, как вы можете видеть здесь:

//creates a new object at the given location, if existing elements are at the same location this will become a sub-element
        public static function addNewObject(type:String, x:uint, y:uint):void
        {
            //get page code
            var pageCode:XML = pageCodes[curPageId];

            //get deepest element at this position
            var deepestElement:XML = getDeepestElementAtPos(pageCode, 0, x, y)["xml"];

            //define the new element
            var newElement:XML = <newElement>tmp</newElement>;

            //if it has to be added to the main tree
            if (deepestElement == pageCode)
            {
                pageCode.appendChild(newElement);
            } 
            else
            {
                //add the element to the child found earlier
                deepestElement.appendChild(newElement);

                //update the element in page code
                // ! this is where I am stuck !
            }
        }

Новый элемент временно только для экспериментальных целей. Мне удалось обновить код, если самый глубокий дочерний элемент является основным деревом (поэтому нет соответствующих дочерних элементов). Однако, когда совпадают дочерние элементы или дочерние элементы внутри дочерних элементов, я понятия не имею, как обновить главное дерево с помощью обновленного самого глубокого дочернего элемента.

Не работает следующее:

pageCode.insertChildAfter(deepestElement, newElement);

Потому что, по-видимому, это работает только в том случае, если deepestElement является прямым дочерним элементом pageCode, а не дочерним по отношению к дочернему элементу (или даже дальше).

Итак, вопрос: как мне обновить pageCode, чтобы он содержал обновленный дочерний элемент deepestElement, даже если этот дочерний элемент является дочерним по отношению к дочернему элементу и т. Д.

Заранее спасибо, вся помощь очень ценится.

Ответы [ 2 ]

1 голос
/ 24 декабря 2009

Я понял, что возвращаемый узел, конечно, на самом деле является только ссылкой.Это означает, что, если я дам ему нового ребенка, полный код страницы также будет обновлен.Это работает:

//creates a new object at the given location, if existing elements are at the same location this will become a sub-element
        public static function addNewObject(type:String, x:uint, y:uint):void
        {
            //get page code
            var pageCode:XML = pageCodes[curPageId];

            //get deepest element at this position
            var deepestElement:XML = getDeepestElementAtPos(pageCode, 0, x, y)["xml"];

            //define the new element
            var newElement:XML = <newElement>tmp</newElement>;

            //add the new element to the code
            deepestElement.appendChild(newElement);
        }
0 голосов
/ 23 декабря 2009

Вы, вероятно, должны получить parentNode элемента deepestElement и работать на этом узле. Сначала удалите старую версию узла, а затем вставьте обновленную. Другой вариант, который, вероятно, более эффективен, это просто обновить атрибуты и / или значение элемента deepestElement без необходимости его замены.

например:

var parent:XMLNode = oldDeepestElement.parentNode;
oldDeepestElement.removeNode();
parent.appendChild(newDeepestElement);

Я не пробовал код, но что-то вроде этого должно работать. В любом случае, как я уже сказал, я бы сначала рассмотрел вопрос об изменении атрибутов узла, а не самого узла, если это возможно.

...