I need to be able to take an array of numbers, and find the corresponding node in an XML tree.
So, if my array was Array(0,2,1,2) I need to be able to get this:
xmlSet[0].childNodes[2].childNodes[1].childNodes[2].childNodes
If the array was always a fixed length, this would be no problem. But it's not a fixed length, so I'm having a hell of a time figuring out how to translate that into the xml traverse.
Any help would be GREATLY appreciated. I'm freaking out because without a solution for this I'm way behind on something...
Thanks 
Which nodes are you traversing through? Are you trying to find children of children or always the same root node level? I'm not understanding.
AS2 or AS3?
AS2.
Not always trying to find the children, but I basically want to end up looking at that last node, whether it's a parent with children, or just the final node by itself. I can take it from there - figuring out the context of the final node, but I can't figure out how to take dynamic steps to get there (an unknown number of levels deep).
OH I understand now. That's a good chunk of code to write. I'll try something later. Maybe someone else can jump in.
How I handled that last time was passing the children around to Objects that could remember what node they would need versus trying to map multi-level children in AS2.
If I figure something out I'll post it. This is one area AS3 is 100% better.
Thanks for the info Storm.
I figured, after wracking my brain for a few hours trying to figure out a solution, that maybe I had opened a can of worms...
I tried storing the info in Objects, but I still end up having to deal with different amounts on info for different objects, so I'm back to needing to be able to find children at different depths. So besides just creating a bunch of if statements to check the length of the object, and working from there, I'm at a loss.
i just knocked together a simple recursive function to do what you're after. I used arrays because i couldn't be arsed writing some stub xml, but since .childNodes is an array, you shouldn't have to tweak it much.
var source:Array = [ [ 1, 2, 3, 4 ], [ 1, 2, [ 5, 6, 7, [ 8, 9, 10, [11, 12, 13, 14] ] ], 4 ] ];
var indicies:Array = [1, 2, 3, 3];
function traverse ( start:Array, indicies:Array ):* { if ( indicies.length > 0 ) { var index:int = indicies[0]; indicies.splice(0, 1); return traverse(start[index], indicies); }else { return start; } }
var val:Array = traverse(source, indicies);
// val should be the same as source[1][2][3][3];
trace ( "direct : " + source[1][2][3][3] ); //11,12,13,14 trace ( "recursive : " + val ); //11,12,13,14
hope it helps,
A
Very cool - much appreciated Lithium!
I suspect you need a generic xml parser, this might be usefull?
import com.dynamicflash.utils.Delegate;
class net.justinfront.XmlNodeToObjArray {
var inputNode: XMLNode;
var obj: Object;
var addName: Boolean;
var outPutTxt: Boolean;
var updateProgress: Function;
var txt: String = "";
var xmlString: String = "";
var place: MovieClip;
var _name: String = "my XML Parser";
var author: String = "jlm at justinfront dot net"
var nom: String;
public function XmlNodeToObjArray(_inputNode:XMLNode, _addName:Boolean, _outPutTxt:Boolean, _nom: String )
{
addName = _addName || false;
outPutTxt = _outPutTxt || false;
inputNode = _inputNode;
nom = _nom || 'xmlObj';
init();
}
private function init()
{
var theNode = inputNode;//.childNodes[0];
obj = {};
if( addName ){
obj._name = nom;
obj.toString = Delegate.create( this, returnFileName )
obj.toXML=function(){
return ".childNodes[0]";
}
}
["ASSetPropFlags"](obj,['toString','_name','attributes'],1,1);
getChildren(theNode, 0, obj, ".childNodes[0]");
if(outPutTxt)
{
trace(txt);
}
}
private function returnFileName()
{
return '('+nom+')'
}
private function getChildren(place:XMLNode, lev:Number, mother:Object, xmlMother:String) {
if (place.hasChildNodes()) {
var i:Number;
var anodeName:String;
var anode:XMLNode;
var temp:Object;
var tempAtt:Object;
var atts:String;
var last_anode:String='';
var counter:Number=0;
var oldTemp:Object;
for (i=0; i<place.childNodes.length; i++) {
anode = place.childNodes[i];
anodeName = anode.nodeName;
if (anodeName == null) {
if (outPutTxt) {
txt += mother+".textValue"+" = "+anode.nodeValue+"\n";
}/*
temp = (mother[anodeName]={});
temp.toXML=function(){
return xmlMother+".childNodes["+String(i)+"].nodeValue";
}
(["ASSetPropFlags"])(temp,['toXML'],1,1);
*/
mother.textValue = cast(anode.nodeValue);
break;
} else {
if (addName) {
if(anodeName == last_anode && last_anode != ""){
last_anode = anodeName;
if(!( (mother[anodeName]) instanceof Array)){
//trace("creating and array"+anodeName);
oldTemp = temp;
temp = (mother[anodeName]=[]);
counter=0;
temp=(mother[anodeName][counter]=oldTemp);
temp._name=anodeName+"["+counter+"]";
counter++;
}
temp=(mother[anodeName][counter]={});
temp._name=anodeName+"["+counter+"]";
counter++;
} else {
last_anode = anodeName;
temp = (mother[anodeName]={});
temp._name = anodeName;
}
temp.toString = function() {
return mother+"."+this._name;
};
temp.toXML=function(){
return xmlMother+".childNodes["+String(i)+"]";
}
//if(place.attributes.length) length check
temp.attributes={};
tempAtt=temp.attributes;
for(atts in anode.attributes){
tempAtt[atts]=cast(anode.attributes[atts]);
tempAtt[atts]._name=atts;
tempAtt[atts].toString=function(){
return mother+"."+atts;
};
tempAtt[atts].toXML=function(){
trace('test info '+xmlMother+".childNodes["+i+"].attributes."+atts)
return xmlMother+".childNodes["+i+"].attributes."+atts;
}
//hide properties from for loops
(["ASSetPropFlags"])(tempAtt[atts],['toString','_name','toXML'],1,1);
}
//hide properties from for loops
(["ASSetPropFlags"])(temp,['toString','_name','attributes','toXML'],1,1);
getChildren(place.childNodes[i], lev+1, temp, temp.toXML());
} else {
temp.attributes={};
tempAtt=temp.attributes;
for(atts in anode.attributes){
tempAtt[atts]=cast(anode.attributes[atts]);
}
//hide properties from for loops
(["ASSetPropFlags"])(temp,['attributes'],1,1);
getChildren(place.childNodes[i], lev+1, mother[anodeName]={});
}
}
}
}
}
public function get instance():Object{
return obj;
}
// returns the most appropriate type
private function cast( str: String ): Object
{
if( str.toLowerCase() == 'true' )
{
return true
}
if( str.toLowerCase() == 'false' )
{
return false
}
var num=Number(str);
if( isNaN( str ) )
{
return str
}else {
return num
}
}
}