-1

If anyone can offer an explanation for this one, I'd LOVE to see it! I was required to append a legacy application to display 20 random questions from an XML data source, as opposed to the total of 70 questions that are part of the original XML. No big deal, right? WRONG! I got it to work just fine in the end, but it's a total HACK! For some reason, some of the nodes that I am appending to a dynamically generated XML document are being returned as "undefined". I kept getting between 16 and 20 questions to render until I modified my iteration from a 'for' loop to a 'do while' loop with the appropriate number of XMLNodes as the condition of the 'do while' loop. Can anyone offer an explanation? Below is the code, with some notes for the reader :

function editXML(xml:XML):XML {

var node:XMLNode = xml.firstChild;
var newNode:XMLNode = new XMLNode();
var nodeArray:Array = new Array();
var usedNodes:Array = new Array();
var totalNodes:Number = node.lastChild.childNodes.length - 1; 
var nextNode:Number;
var returnNode:XMLNode = new XMLNode();
var tempNode:XMLNode;
var buildNode:XMLNode;
var addNode:Boolean = true;

var tempXML:XML = new XML();
var pagesNode:XMLNode = tempXML.createElement("pages");
tempXML.appendChild(pagesNode);
tempXML.appendChild(node.childNodes[0]);
tempXML.appendChild(node.childNodes[1]);
tempXML.appendChild(node.childNodes[2]);
var questionsNode:XMLNode = tempXML.createElement("pages");
tempXML.firstChild.appendChild(questionsNode);
do
{


    nextNode = Math.floor(Math.random()*totalNodes); 
             **//random number to represent random node**
    //trace(nextNode + " nextNode");
    **//check usedNodes Array to look for node.childNodes[nextNode]. If it already exists, skip and reloop.**
    trace(node.childNodes[1].childNodes[nextNode] + " : pre building Node " + totalNodes);
    if(usedNodes.length == 0)
    {
        buildNode = new XMLNode();
        buildNode.nodeName = node.childNodes[1].childNodes[nextNode].nodeName;
                                       buildNode.nodeValue = node.childNodes[1].childNodes[nextNode].nodeValue;
        tempXML.firstChild.lastChild.appendChild(node.childNodes[1].childNodes[nextNode])
        usedNodes.push(node.childNodes[1].childNodes[nextNode]);
        nodeArray.push(node.childNodes[1].childNodes[nextNode]);
        trace("adding first node : " + nodeArray.length); 
        addNode = false;
    }
    else
    {
       for(var j:Number = 0; j < usedNodes.length; j++)
       {
           if(usedNodes[j] == node.childNodes[1].childNodes[nextNode])
           {                
               addNode = false;
               trace("skipping node : " + nodeArray.length);
           }
       }
    }
    **//if node not in usedNodes, add node to XML**
    if(addNode)
    {           


        trace(node.childNodes[1].childNodes[nextNode] + " : building Node"); **//This trace statement produced a valid node**
        tempXML.firstChild.lastChild.appendChild(node.childNodes[1].childNodes[nextNode]);
      **//Before modifying the code from adding nodes to the xml from an Array called 'nodeArray' in a for loop to adding nodes directly to the xml in a do while loop with the length of the xml node used to retrieve data for the questions as the condition, I was not always getting 20 questions. Some of the nodes were being rendered as 'undefined' and not appended to the xml, even though they were traced and proven valid before the attemp to append them to the xml was made**
        usedNodes.push(node.childNodes[1].childNodes[nextNode]);            
  }

    addNode = true;
}
while(tempXML.firstChild.lastChild.childNodes.length <= 19);
trace(tempXML.firstChild.lastChild.childNodes.length + " final nodes Length");

courseXML = tempXML;
//removes the old question list of 70 and replaces it with the new question list of 20. Question list is the last node.


return tempXML;

}

If I had my choice, I would have rebuilt the whole application in Flex with AS3. I didn't have that choice. If anyone can explain this mystery, PLEASE DO! Thank you in advance!

1 Answers1

0

I don't really understand exactly what the original issue is, since you didn't post your non-working code, only your not terribly great, but working, code. What I do see is simply an issue of an approach that isn't the best one, regardless of language.

What I'd suggest is this:

  1. If for some reason you need to keep your original 70 questions of XML, make a copy by calling toString() and then casting back to XML. This will break any object dependencies that might exist (though I have no idea if AS2 XML acts like real objects or not).
  2. On each loop, DELETE the node you added to the new XML. That way you won't have to do that inner loop to check if you already used it (which is really inefficient).
  3. Since you're deleting it, why not just move it into the new XML rather than creating a new node? That way you won't need to use the helper variable Florian suggested instead of several expressions that look like node.childNodes[1].childNodes[nextNode].nodeName;
  4. At this point, you'll be abe to just loop 20 times or you could keep while looping...It doesn't matter. Either will result in 20 loops with 20 random questions.
Amy Blankenship
  • 6,485
  • 2
  • 22
  • 45