Created
March 25, 2014 00:54
-
-
Save bennadel/9753127 to your computer and use it in GitHub Desktop.
Deleting XML Node Arrays From A ColdFusion XML Document
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!--- Create a ColdFusion XML document. ---> | |
<cfxml variable="xmlGirls"> | |
<girls> | |
<girl id="1"> | |
<name>Hayden Panettiere</name> | |
<hair>Blonde</hair> | |
</girl> | |
<girl id="2"> | |
<name>Christina Cox</name> | |
<hair>Blonde</hair> | |
</girl> | |
<girl id="3"> | |
<name>Winona Ryder</name> | |
<hair>Brunette</hair> | |
</girl> | |
<girl id="4"> | |
<name>Minnie Driver</name> | |
<hair>Brunette</hair> | |
</girl> | |
<girl id="5"> | |
<name>Julia Stiles</name> | |
<hair>Blonde</hair> | |
</girl> | |
</girls> | |
</cfxml> | |
<!--- Query for all blonde xml nodes. ---> | |
<cfset arrBlondeGirls = XmlSearch( | |
xmlGirls, | |
"//girl[ hair/text() = 'Blonde' ]" | |
) /> | |
<!--- Delete all blondes from the document. ---> | |
<cfset XmlDeleteNodes( | |
xmlGirls, | |
arrBlondeGirls | |
) /> | |
<!--- | |
Output the modified XML document, which should, at | |
this point, only contain Brunetted. | |
---> | |
<cfdump | |
var="#xmlGirls#" | |
label="xmlGirls - After Blondes Have Been Removed" | |
/> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<cffunction | |
name="XmlDeleteNodesJava" | |
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> | |
<!--- Loop over the nodes. ---> | |
<cfloop | |
index="LOCAL.Node" | |
array="#ARGUMENTS.Nodes#"> | |
<!--- Get the parent node. ---> | |
<cfset LOCAL.ParentNode = LOCAL.Node.GetParentNode() /> | |
<!--- | |
Check to see if the parent was found. If not, then | |
we are not dealing with an Element node. | |
---> | |
<cfif StructKeyExists( LOCAL, "ParentNode" )> | |
<!--- | |
Get the previous sibling of the node in the | |
question. If there is no previous sibling, this | |
will return NULL and it will tell us that | |
the target node is the first node in the child | |
nodes array. | |
---> | |
<cfset LOCAL.PrevNode = LOCAL.Node.GetPreviousSibling() /> | |
<!--- | |
Check to see if the previous node was found | |
or if is null (which will have removed the | |
struct key). | |
---> | |
<cfif StructKeyExists( LOCAL, "PrevNode" )> | |
<!--- | |
We have the prev node. Use that to get the | |
Java version of our ChildNode and delete from | |
the parent. | |
---> | |
<cfset LOCAL.ParentNode.RemoveChild( | |
LOCAL.PrevNode.GetNextSibling() | |
) /> | |
<cfelse> | |
<!--- | |
The previous node didn't exist which means | |
that our target node is the first node in the | |
child array. | |
---> | |
<cfset LOCAL.ParentNode.RemoveChild( | |
LOCAL.ParentNode.GetFirstChild() | |
) /> | |
</cfif> | |
</cfif> | |
</cfloop> | |
<!--- Return out. ---> | |
<cfreturn /> | |
</cffunction> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment