|
<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 we |
|
only have one node passed in, let's create an array of |
|
it 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 delete |
|
these via the XmlChildren array of the parent, so we |
|
need 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 nodes |
|
that 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 XmlChildren |
|
element. If it does, then it is an element node. If |
|
not, 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 out |
|
list of nodes to delete. |
|
---> |
|
<cfset ArrayDeleteAt( |
|
ARGUMENTS.Nodes, |
|
LOCAL.NodeIndex |
|
) /> |
|
|
|
</cfif> |
|
|
|
</cfloop> |
|
|
|
|
|
<!--- |
|
Now that we have flagged the nodes that need to be |
|
deleted, we can loop over them to find their parents. |
|
All nodes should have a parent, except for the root |
|
node, 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't |
|
delete the root node, and we also be deleting other |
|
elements as well - make sure it is all playing |
|
nicely together. As a final check, make sure that |
|
out parent has children (only happens if we are |
|
dealing 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 loop |
|
over it's children to one the nodes flagged as |
|
deleted (and delete them). As we do this, we |
|
want to loop over the children backwards so that |
|
we don't go out of bounds as we start to remove |
|
child 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 flagged |
|
for 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 the |
|
deletion flag. This node might still be |
|
used by another part of the program. |
|
---> |
|
<cfset StructDelete( |
|
LOCAL.Node.XmlAttributes, |
|
"delete-me-flag" |
|
) /> |
|
|
|
</cfif> |
|
|
|
</cfloop> |
|
|
|
</cfif> |
|
|
|
</cfloop> |
|
|
|
<!--- Return out. ---> |
|
<cfreturn /> |
|
</cffunction> |