2012-03-26 44 views
0

我有一個廣泛的菜單,我想快速搜索和操作菜單項。是否有可能搜索ID的列表,可以說沿着coldfusion xmlsearch找到多個節點

list contains ("0,57,19,22,30,31,32,33,34,36,45,53,63,58,59,23,24,25,26,27,28,29,37,38,39,40,41,42,43,44,46,47,48,50,51,52,54,55,16", "45") 

例如節點線的東西:

<li class="standby" id="id61"> 

截至目前,我在CFSCRIPT使用循環

 if(listLen(IdsToRemove.List,",") GT 1){ 
      for(i=1;i lte listLen(IdsToRemove.List);i=i+1) { 
       valueToFind="li[@id='" & listGetAt(IdsToRemove.List,i) & "']"; 
       findNode=XmlSearch(MyNavigation.myMenu,"//" & valueToFind); 
       Instance.UDFLibrary.XmlDeleteNodes(XmlDocument=MyNavigation.myMenu,Nodes=findNode); 
      } 
     } 

我真的希望搜索一個列表並一次刪除所有節點。想法?

回答

1

您可以在xpath表達式中使用來搜索字符串。如果您將該字符串視爲列表,則可以跳過外部循環。

var ids = ListChangeDelims(IdsToRemove.List, ',', ' '); // commas to spaces 
var nodes = XmlSearch(MyNavigation.myMenu,"//li[contains(' " & ids & " ', concat(' ', substring(@id,3), ' '))]"); 

IDS會是這樣的「0 57 19」和concat(' ', substring(@id,3), ' ')會是這樣的「0」,因此上面的表達式基本上ListFind(的冗長版本)使用所有但的前2個字符節點ID。

+0

非常感謝你的幫助,我做了一些修改,完成你的盒子,並檢查了好這個問題去 – 2012-03-26 14:36:52

0

以下是完整的安裝,我使用的情況下,其他人需要這方面的幫助:

<cfscript> 
    testme=structnew(); 
    testme.menu=xmlNav(buildNav(qgetNav)); 
    testme.menustring=tostring(xmlNav(buildNav(qgetNav))); 

    testme.valueToFind="li[@id='id56']"; 
    testme.findNode=XmlSearch(testme.menu,"//" & testme.valueToFind); 

    testme.List="0 16 41 42 43 16 41 42 43 16 41 42 43 16 41 42 43 "; 
    testme.ids = ListChangeDelims(testme.List,' ',','); // commas to spaces 
    testme.nodes = XmlSearch(testme.menu,"//li[contains(' " & testme.ids & " ', concat(' ', substring(@id,3), ' '))]"); 

    XmlDeleteNodes(XmlDocument=testme.menu,Nodes=testme.nodes); 

</cfscript> 
<cfdump var="#testme#"> 

<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="xmlNav" returntype="xml"> 
    <cfargument name="aNav" type="array"> 
    <cfset var navXML=""> 
    <cfxml variable="navXML"> 
     <cfoutput> 
      #xmlNavList(aNav=arguments.aNav)# 
     </cfoutput> 
    </cfxml> 
    <cfreturn navXML> 
</cffunction> 

<cffunction name="xmlNavList" returntype="any"> 
    <cfargument name="aNav" type="array"> 
    <cfargument name="level" type="numeric" default="0"> 
    <cfset var iNav = ""> 
    <ul 
     <cfif arguments.level GT 0> 
      class="sub-nav-main-links nestingLevel<cfoutput>#arguments.level#</cfoutput>" 
     <cfelse> 
      id="nav-main-links" 
     </cfif> 
     > 
     <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 xmlNavList(iNav.aChildren,arguments.level+1)> 
        </cfif> 
       </li> 
      </cfoutput> 
     </cfloop> 
    </ul> 
</cffunction> 

<cffunction name="xmlGetNodePath" access="public" returntype="string"output="false" hint="I take a given XML node and return it's full XML path."> 
    <cfargument name="node" type="any" required="true" hint="I am the XML node who's location is being reverse engineered."/> 
    <cfset var local={ } /> 
    <cfset local.fullPath="" /> 
    <cfset local.marker="udf:xmlGetNodePath" /> 
    <cfset local.node=arguments.node /> 
    <cfloop condition="true"> 
     <cfif (!structKeyExists(local.node, "xmlParent") || !structKeyExists(local.node.xmlParent, "xmlName"))> 
      <cfbreak /> 
     </cfif> 
     <cfset local.node.xmlAttributes[ local.marker ]=true /> 
     <cfset local.siblings=xmlSearch(local.node.xmlParent, ("./" & local.node.xmlName)) /> 
     <cfloop index="local.siblingIndex" from="1" to="#arrayLen(local.siblings)#"step="1"> 
      <cfif structKeyExists(local.siblings[ local.siblingIndex ].xmlAttributes,local.marker)> 
       <cfset local.fullPath=("/" & local.node.xmlName & "[" & local.siblingIndex& "]" & local.fullPath) /> 
       <cfbreak /> 
      </cfif> 
     </cfloop> 
     <cfset structDelete(local.node.xmlAttributes, local.marker) /> 
     <cfset local.node=local.node.xmlParent /> 
    </cfloop> 
    <cfreturn local.fullPath /> 
</cffunction> 

<cffunction name="XmlDeleteNodes" access="public" returntype="void" output="false" hint="I remove a node or an array of nodes from the given XML document."> 
    <!--- Define arugments. ---> 
    <cfargument name="XmlDocument" type="any" required="true" hint="I am a ColdFusion XML document object."/> 
    <cfargument name="Nodes" type="any" required="false" hint="I am the node or an array of nodes being removed from the given document." /> 
    <!--- Define the local scope. ---> 
    <cfset var LOCAL=StructNew() /> 
    <!---Check to see if we have a node or array of nodes. If weonly have 
    one node passed in, let's create an array ofit so we can assume an array 
    going forward.---> 
    <cfif NOT IsArray(ARGUMENTS.Nodes)> 
     <!--- Get a reference to the single node. ---> 
     <cfset LOCAL.Node=ARGUMENTS.Nodes /> 
     <!--- Convert single node to array. ---> 
     <cfset ARGUMENTS.Nodes=[ LOCAL.Node ] /> 
    </cfif> 
    <!---Flag nodes for deletion. We are going to need to deletethese via 
    the XmlChildren array of the parent, so weneed to be able to differentiate 
    them from siblings.Also, we only want to work with actual ELEMENT nodes,not 
    attributes or anything, so let's remove any nodesthat are not element nodes.---> 
    <cfloop index="LOCAL.NodeIndex" from="#ArrayLen(ARGUMENTS.Nodes)#" to="1" step="-1"> 
     <!--- Get a node short-hand. ---> 
     <cfset LOCAL.Node=ARGUMENTS.Nodes[ LOCAL.NodeIndex ] /> 
     <!---Check to make sure that this node has an XmlChildrenelement. If it 
     does, then it is an element node. Ifnot, then we want to get rid of it.---> 
     <cfif StructKeyExists(LOCAL.Node, "XmlChildren")> 
      <!--- Set delet flag. ---> 
      <cfset LOCAL.Node.XmlAttributes[ "delete-me-flag" ]="true" /> 
     <cfelse> 
      <!---This is not an element node. Delete it from outlist of nodes to delete.---> 
      <cfset ArrayDeleteAt(ARGUMENTS.Nodes,LOCAL.NodeIndex) /> 
     </cfif> 
    </cfloop> 
    <!---Now that we have flagged the nodes that need to bedeleted, we can 
    loop over them to find their parents.All nodes should have a parent, except 
    for the rootnode, which we cannot delete.---> 
    <cfloop index="LOCAL.Node" array="#ARGUMENTS.Nodes#"> 
     <!--- Get the parent node. ---> 
     <cfset LOCAL.ParentNodes=XmlSearch(LOCAL.Node, "../") /> 
     <!---Check to see if we have a parent node. We can'tdelete the root node, 
     and we also be deleting otherelements as well - make sure it is all playingnicely 
     together. As a final check, make sure thatout parent has children (only 
     happens if we aredealing with the root document element).---> 
     <cfif (ArrayLen(LOCAL.ParentNodes) AND StructKeyExists(LOCAL.ParentNodes[1], "XmlChildren"))> 
      <!--- Get the parent node short-hand. ---> 
      <cfset LOCAL.ParentNode=LOCAL.ParentNodes[ 1 ] /> 
      <!---Now that we have a parent node, we want to loopover it's children 
      to one the nodes flagged asdeleted (and delete them). As we do this, wewant 
      to loop over the children backwards so thatwe don't go out of bounds as 
      we start to removechild nodes.---> 
      <cfloop index="LOCAL.NodeIndex" from="#ArrayLen(LOCAL.ParentNode.XmlChildren)#"to="1" step="-1"> 
       <!--- Get the current node shorthand. ---> 
       <cfset LOCAL.Node=LOCAL.ParentNode.XmlChildren[ LOCAL.NodeIndex ] /> 
       <!---Check to see if this node has been flaggedfor deletion.---> 
       <cfif StructKeyExists(LOCAL.Node.XmlAttributes, "delete-me-flag")> 
         <!--- Delete this node from parent. ---> 
         <cfset ArrayDeleteAt(LOCAL.ParentNode.XmlChildren,LOCAL.NodeIndex) /> 
         <!---Clean up the node by removing thedeletion flag. This node might still 
         beused by another part of the program.---> 
         <cfset StructDelete(LOCAL.Node.XmlAttributes, "delete-me-flag") /> 
        </cfif> 
      </cfloop> 
     </cfif> 
    </cfloop> 
    <!--- Return out. ---> 
    <cfreturn /> 
</cffunction> 
+1

哇,這是有點粗魯的克里斯。您使用我的答案解決了問題,標記了我的答案是正確的,然後發佈了一段代碼,這與您所問的問題(除了使用我的答案的部分除外)基本無關,並且給出了正確答案的功勞。 – SpliFF 2012-03-30 04:17:50

+0

我認爲我們應該標記我們最終在完成時使用了什麼。我的錯誤,不用擔心,我把它扔回去了。我只是想讓其他人看到完整的解決方案。我試圖編輯您的帖子,但您從未接受我所要求的修改。我們可以把它們合併起來嗎似乎這對於每個人來說都會更有意義。 – 2012-03-30 22:22:13

+0

感謝您的放棄權利。我花了很多時間回答我的問題。我的投訴與你的問題有關「尋找多個節點」和「通過列表搜索」有關,而不是關於XmlDeleteNodes的實現(因爲它看起來你已經有了)。完整添加XmlDeleteNodes代碼可能對其他人有所幫助,但它不是真正的答案。 – SpliFF 2012-04-01 06:35:10