Howto get the deepest XML child matching certain attributes relative to the parrents in actionscript 3?
If I have the following XML in 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>
This is just an example. Now, what I want to do is the following:
get the deepest child element with x, y, width and height attributes which is within a certain location. So, if the given location is 50x100 then ((child.@x <= x) && (child.@x + child.@width >= x) && (child.@y <= y) && (child.@y + child.@height >= y))
must be valid
In this case it should return the second child element named child with attributes x=0 and y=0 - the code should also keep in mind that the childs of elements' positions are relative to the parents position. So, if the child's X is 0 and the parent's X is 100 then the absolute child position is 100.
I'm struggeling to get this right, could anyone help me out?
In the end, the method
getD开发者_如何学PythoneepestChildAtLoc(50, 100)
should in the above example code return
<child x="0" y="0" width="100" height="100">
content
</child>
I hope this makes sense. Thank in advance.
Edit:
Judging by the lack of replies this might not be making a lot of sense. In any way, this is what I came up with so far - though it returns "null" all the time so obviousely there is a flaw:
//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;
}
Notice also how the depth variable has not been used yet, while it obviousely should as the one with the highest depth should be returned. I'm not sure where to put this in though... any help?
After three days of overdosis coffee, headache and a ton of googling aswell as way too much trial-and-error I found the solution.
//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;
}
精彩评论