title: coldfusion xml menu
body: <p>I am working to build a menu in coldfusion based on xml.  </p>
  
  <p>current working function:</p>
  
  <pre><code>&lt;cffunction name="xmlNav" access="private" returntype="struct" output="false"&gt;
      &lt;cfargument name="qGetNav" type="query" required="true"&gt;
      &lt;cfscript&gt;
          var qNav=Arguments.qGetNav;
          var xmlNav=StructNew();
          var myXmlDoc=xmlNew();
          var route='';
          myXmlDoc.XMLRoot = XMLElemNew(myXmlDoc,"UL");
          myXmlDoc.UL.xmlAttributes.ID="nav-main-links";
          for(q=1;q&lt;=qNav.recordCount;q++){
  
  
              //setup li
                  myXmlDoc.UL.XmlChildren[q]=XmlElemNew(myXmlDoc,"LI");
                  myXmlDoc.UL.XmlChildren[q].xmlAttributes.ID="id" &amp; qNav["navid"][q];
                  myXmlDoc.UL.XmlChildren[q].xmlAttributes.CLASS="standby";
              //setup route
                  myXmlDoc.UL.XmlChildren[q].a=XmlElemNew(myXmlDoc,"A");
                  route=qNav["Route"][q];
                  if(qNav["Version"][q] Eq "CB"){
                      route="/?event=" &amp; route;
                  }
                  else if(qNav["Version"][q] Eq "L"){
                      route="http://" &amp; route;
                  }
                  myXmlDoc.UL.XmlChildren[q].A.xmlAttributes.HREF=route;
                  myXmlDoc.UL.XmlChildren[q].A.xmlAttributes.TARGET=qNav["LinkTarget"][q];
                  myXmlDoc.UL.XmlChildren[q].A.xmlAttributes.TITLE=qNav["LinkTitle"][q];
              //setup route text
                  myXmlDoc.UL.XmlChildren[q].A.SPAN=XmlElemNew(myXmlDoc,"SPAN");
                  myXmlDoc.UL.XmlChildren[q].A.SPAN.xmlText=qNav["TextDesc"][q];
                  myXmlDoc.UL.XmlChildren[q].A.SPAN.FONT=XmlElemNew(myXmlDoc,"FONT");
                  myXmlDoc.UL.XmlChildren[q].A.SPAN.FONT.xmlAttributes.CLASS="menuItemType";
                  myXmlDoc.UL.XmlChildren[q].A.SPAN.FONT.xmlText="(" &amp; qNav["Version"][q] &amp; ")";
  
  
  
  
          }
          xmlNav.xmlNavString=toString(myXmlDoc);
          xmlNav.xmlNavString=replaceNoCase(xmlNav.xmlNavString,"&amp;gt;",CHR(62),"all");
          xmlNav.xmlNavString=replaceNoCase(xmlNav.xmlNavString,"&amp;lt;",CHR(60),"all");
          xmlNav.xmlNavString=replaceNoCase(xmlNav.xmlNavString,"&amp;amp;",CHR(38),"all");
          xmlNav.xmlNav=myXmlDoc;
  
          return xmlNav;
      &lt;/cfscript&gt;
  &lt;/cffunction&gt;
  </code></pre>
  
  <p>I need to account for children and I am running into some significant difficulty.  Here is the example I am using based on arrays and structs:</p>
  
  <pre><code>&lt;cffunction name="arrayNav" access="private" returntype="struct" output="false"&gt;
          &lt;cfargument name="qGetNav" type="query" required="true"&gt;
          &lt;cfscript&gt;
              var qNav=Arguments.qGetNav;
              var arrayNav=StructNew();
              var aNavTree = arrayNew(1);
              var aNavMenuItems = arrayNew(1);
              var sNavLookup = structNew();
              for(q=1;q&lt;=qNav.recordCount;q++){
                  sThis = structNew();
                  sThis.data = structNew();
                  sThis.data.navid = qNav["navid"][q];
                  sThis.data.Route = qNav["Route"][q];  
                  sThis.data.Version = qNav["Version"][q];
                  if(qNav["Version"][q] Eq "CB"){
                      arrayAppend(aNavMenuItems,qNav["Route"][q]);
                  }
                  sThis.data.LinkTarget = qNav["LinkTarget"][q];
                  sThis.data.LinkTitle = qNav["LinkTitle"][q];
                  sThis.data.TextDesc = qNav["TextDesc"][q];
                  sThis.children = arrayNew(1);
                  /*
                      now loop through
                      avoid dupes from the levelid, this should prob be handled in the query above by only selecting
                      the right levels, or using a select distinct without the levelid in there
                  */
                  if(Not structKeyExists(sNavLookup,qNav["navid"][q])){
                      sNavLookup[qNav["navid"][q]] = sThis;
                  }
                  else{
                      //do nothing    
                  }
                  if(qNav["NavParentId"][q] EQ 0){
                      arrayAppend(aNavTree, sThis);
                  }
                  else{
                      if(structKeyExists(sNavLookup, qNav["NavParentId"][q])){
                          arrayAppend(sNavLookup[qNav["NavParentId"][q]].children, sThis);
                      }
                      else{
                        //parent not found  
                      }   
                  }
              }
              arrayNav.arrayNav=aNavTree;
              arrayNav.arrayNavMenuItems=aNavMenuItems;
              return arrayNav;
          &lt;/cfscript&gt;
      &lt;/cffunction&gt;
  </code></pre>
  
  <p>hoping to avoid recursion if I can. so my question is how can add a block to the for loop that searches the xml file for the parent node and adds children nodes to it.  I am literally stuck on the search piece.  so far I can find the node for example using   <code>xmlNav.findNode=XmlSearch(myXmlDoc,"/UL/LI[@ID='id57']");</code> to find the position, but having trouble inserting the item there.</p>