Как получить самый глубокий дочерний элемент XML, соответствующий определенным атрибутам относительно частей в ActionScript 3? - PullRequest
0 голосов
/ 22 декабря 2009

Если у меня есть следующий XML в ActionScript 3:

<xml>
   <element1 x="10" y="10" width="200" height="200">
       <child>text</child>
       <child x="0" y="0" width="100" height="100">
            content
       </child>
   </element1>
   <element2 x="10" y="10" width="200" height="200">
   </element2>
   <element3>
   </element3>
</xml>

Это всего лишь пример. Теперь я хочу сделать следующее: получить самый глубокий дочерний элемент с атрибутами x, y, width и height, который находится в определенном месте. Таким образом, если данное местоположение 50х100, то ((child.@x <= x) && (child.@x + child.@width >= x) && (child.@y <= y) && (child.@y + child.@height >= y)) должно быть действительным

В этом случае он должен возвращать второй дочерний элемент с именем child с атрибутами x = 0 и y = 0 - в коде также следует помнить, что позиции потомков элементов относятся к позиции родителей. Таким образом, если X дочернего элемента равен 0, а родительский X равен 100, то абсолютная дочерняя позиция равна 100.

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

В конце концов, метод

getDeepestChildAtLoc(50, 100)

в приведенном выше примере код должен возвращать

<child x="0" y="0" width="100" height="100">
            content
       </child>

Надеюсь, это имеет смысл. Спасибо заранее.

Edit:

Судя по отсутствию ответов, это может не иметь большого смысла. В любом случае, это то, что я придумал до сих пор - хотя он возвращает «ноль» все время, так что очевидно, что есть недостаток:

//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];
   trace(recProcessXML(pageCode, 0, x, y));
  }

  //recursively process childs to get the deepest child around the given position
  private static function recProcessXML(curElement:XML, depth:uint, targetX:uint, targetY:uint, totParentX:uint = 0, totParentY:uint = 0):XML
  {
   if (!curElement.children().length() > 0)
   { //this element has no further children
    return curElement;
   }
   else
   { //this element has further children
    var newChild:XML;
    var testChild:XML;
    for each (var child:XML in curElement.children())
    { //loop all children
     if (posInsideNode(child, totParentX, totParentY, targetX, targetY))
     { //if the child is still around the given position
      testChild = recProcessXML(child, depth + 1, targetX, targetY, child.@x + totParentX, child.@y + totParentY);
      if (testChild)
      { //if this child has further children
       newChild = testChild;
      }
     }
    }
    return newChild;
   }
   return null;
  }

  //returns whether the given position is inside the node
    private static function posInsideNode(child:XML, offsetX:uint, offsetY:uint, targetX:uint, targetY:uint):Boolean
    {
        trace("posInsideNode child: " + child.localName() + " -> " + child);
        //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;
    }

Обратите внимание также на то, что переменная глубины еще не использовалась, хотя она должна, как и та, что должна быть возвращена с наибольшей глубиной. Я не уверен, куда это положить, хотя ... любая помощь?

1 Ответ

0 голосов
/ 23 декабря 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];
            trace(getDeepestElementAtPos(pageCode, 0, x, y)["xml"].toXMLString());
        }

        //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;
        }
...