2012-03-22 67 views
1

我正在努力在基於xml的Coldfusion中構建一個菜單。coldfusion xml菜單

當前工作功能:

<cffunction name="xmlNav" access="private" returntype="struct" output="false"> 
    <cfargument name="qGetNav" type="query" required="true"> 
    <cfscript> 
     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<=qNav.recordCount;q++){ 


      //setup li 
       myXmlDoc.UL.XmlChildren[q]=XmlElemNew(myXmlDoc,"LI"); 
       myXmlDoc.UL.XmlChildren[q].xmlAttributes.ID="id" & 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=" & route; 
       } 
       else if(qNav["Version"][q] Eq "L"){ 
        route="http://" & 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="(" & qNav["Version"][q] & ")"; 




     } 
     xmlNav.xmlNavString=toString(myXmlDoc); 
     xmlNav.xmlNavString=replaceNoCase(xmlNav.xmlNavString,"&gt;",CHR(62),"all"); 
     xmlNav.xmlNavString=replaceNoCase(xmlNav.xmlNavString,"&lt;",CHR(60),"all"); 
     xmlNav.xmlNavString=replaceNoCase(xmlNav.xmlNavString,"&amp;",CHR(38),"all"); 
     xmlNav.xmlNav=myXmlDoc; 

     return xmlNav; 
    </cfscript> 
</cffunction> 

我需要考慮到孩子和我遇到了一些困難顯著。這裏是我使用的基於陣列和結構的示例:

<cffunction name="arrayNav" access="private" returntype="struct" output="false"> 
     <cfargument name="qGetNav" type="query" required="true"> 
     <cfscript> 
      var qNav=Arguments.qGetNav; 
      var arrayNav=StructNew(); 
      var aNavTree = arrayNew(1); 
      var aNavMenuItems = arrayNew(1); 
      var sNavLookup = structNew(); 
      for(q=1;q<=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; 
     </cfscript> 
    </cffunction> 

希望避免遞歸,如果可以的話。所以我的問題是如何將一個塊添加到搜索xml文件的父節點並添加子節點的for循環。我從字面上停留在搜索片上。到目前爲止,我可以找到節點,例如使用xmlNav.findNode=XmlSearch(myXmlDoc,"/UL/LI[@ID='id57']");來查找位置,但無法在該位置插入項目。

+0

問題在哪裏? – Henry 2012-03-23 00:01:36

+0

@Henry我剛纔說得更清楚了,謝謝 – 2012-03-23 00:06:07

+0

基本上它提供了一個查詢「qGetNav」,裏面有所有的菜單項,並且我想動態生成xml – 2012-03-23 00:37:46

回答

0

經過大量的努力和協作,我想與大家分享。以下兩個函數根據以下查詢生成一個xml菜單。我真的希望這可以幫助極客社區中的其他人。

<cfquery name="qGetNav" datasource="pcmenusqldev"> 
select navid,navparentid,navorder,Route,Version,LinkTarget,LinkTitle,TextDesc 
from rhNavRoutesByLevel,rhnavRoutes 
where rhnavRoutes.ID=rhNavRoutesByLevel.NavID And LevelID = 1 
order by navParentId, navOrder, navId 
</cfquery> 

<cfset aNav = buildNav(qgetNav)> 
<cfdump var="#qgetNav#" label="qGetNav" expand="no"> 
<cfdump var="#buildNav(qGetNav)#" expand="no" label="buildNav"> 
<hr><hr><hr> 

<cfset testme=structnew()> 
<cfset testme.menu=buildListXML(aNav)> 
<cfdump var="#testme#"> 

<hr><hr><hr> 
<cfoutput>#buildListXML(aNav)#</cfoutput> 
<hr><hr><hr> 
<cfoutput>#buildList(aNav)#</cfoutput> 

<cffunction name="buildNav" returntype="array"> 
    <cfargument name="qGetNav" type="query"> 
    <cfset var sLU = structNew()> 
    <cfset var aMenu = arrayNew(1)> 
    <cfset var aNavMenuItems = arrayNew(1)> 
    <cfset var sThis = structNew()> 
    <cfloop query="qGetNav"> 
     <cfset sThis = structNew()> 
     <cfset sThis.route = qGetNav.Route> 
     <cfset sthis.textDesc = qGetNav.textDesc> 
     <cfset sthis.linkTitle = qGetNav.linkTitle> 
     <cfset sthis.linkTarget = qGetNav.linkTarget> 
     <cfset sthis.Version = qGetNav.version> 
     <cfif sthis.Version Eq "CB"> 
      <cfset arrayAppend(aNavMenuItems,sThis.route)> 
     </cfif> 
     <cfset sthis.navID = qGetNav.navID> 
     <cfset sthis.aChildren = arrayNew(1)> 
     <cfset sLU[qGetNav.navID] = sThis> 
     <cfif val(qGetNav.navParentID) NEQ 0> 
      <cfset arrayAppend(sLU[qGetNav.navParentID].aChildren, sThis)> 
     <cfelse> 
      <cfset arrayAppend(aMenu, sThis)> 
     </cfif> 
    </cfloop> 
    <cfreturn aMenu> 
</cffunction> 

<cffunction name="buildListXML" returntype="xml"> 
    <cfargument name="aNav" type="array"> 
    <cfset var navXML=""> 
    <cfxml variable="navXML"> 
     <cfoutput> 
      #buildList(aNav=arguments.aNav)# 
     </cfoutput> 
    </cfxml> 
    <cfreturn navXML> 
</cffunction> 

<cffunction name="buildList" returntype="any"> 
    <cfargument name="aNav" type="array"> 
    <cfset var iNav = ""> 
    <ul> 
     <cfloop array="#aNav#" index="iNav"> 
      <cfoutput> 
       <cfif iNav.Version Eq "CB"> 
        <cfset iNav.Route="/?event=" & iNav.Route> 
       <cfelseif iNav.Version Eq "L"> 
        <cfset iNav.Route="http://legacy" & iNav.Route> 
       </cfif> 
       <li class="standby" id="id#iNav.navid#"> 
        <a href="#iNav.route#" title="#iNav.linkTitle#" target="#iNav.linkTarget#"> 
         #iNav.textDesc# <font class="menuItemType">(#iNav.Version#)</font> 
        </a> 
        <cfif arrayLen(iNav.aChildren) GT 0> 
         <cfset buildList(iNav.aChildren)> 
        </cfif> 
       </li> 
      </cfoutput> 
     </cfloop> 
    </ul> 
</cffunction>