Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I delete an xml node by attribute value?

I have an xml object in my coldfusion code that looks like this:

enter image description here

I would like to have the ability to delete a node based on the zip. For example - delete the node that has a zip of '22222'.

I know that I can loop through each node, check the zip, and once I find it execute <cfset ArrayDeleteAt(xmlDoc.terminals.XmlChildren, currentIndex)> to delete that node. But is there any more intuitive way to do this? Any built in coldfusion functions that avoid explicit looping?

like image 386
froadie Avatar asked Jul 11 '26 20:07

froadie


1 Answers

I would use jSoup for this. It's really a HTML parser, but can still be used against XML.

Once you've parsed the XML, selecting and removing by attribute is as simple as...

.select('[zip=22222]').remove()

...but here is a complete example, using jSoup 1.7.2 (earlier versions may have a slightly different API):

<cfsavecontent variable="XmlText">
    <TERMINALS>
        <terminal location="some random location" terminal="25" zip="11111" />
        <terminal location="some other location" terminal="26" zip="22222" />
        <terminal location="some more location" terminal="22" zip="33333" />
    </TERMINALS>
</cfsavecontent>

<cfscript>
    jSoup = createObject('java','org.jsoup.Jsoup');
    Parser = createObject('java','org.jsoup.parser.Parser');

    Dom = jSoup.parse( XmlText , '' , Parser.xmlParser() );

    Dom.select('[zip=22222]').remove();

</cfscript>

<cfdump var=#Dom.outerHtml()# />


For that code to work, CF needs to know about the jSoup classes, so it needs to be able to see the JAR file, which can be achieved in four different ways:

Option 1:
Place the jSoup jar in CF's lib directory - e.g. {cf10}/cfusion/webroot/WEB-INF/lib or {cf9}/webroot/WEB-INF/lib - and restart CF. More info.

Option 2:
Place the jSoup jar in a local directory and setup This.JavaSettings in Application.cfc - this feature was added in CF 10 and Railo 4.0

Option 3:
Place the jSoup jar in a local directory and use JavaLoader to load it (similar to above, but works with any version).

The two createObject lines above should then be replaced with:

jl = new javaloader.JavaLoader([expandPath('./jsoup-1.7.2.jar')]);
jSoup  = jl.create('org.jsoup.Jsoup');
Parser = jl.create('org.jsoup.parser.Parser');

(assuming jar file is in same directory as script)

Option 4:
For Railo and OpenBD, the above options will work, or you can simply reference the path to the JAR file as a third argument to the createObject calls.

like image 91
Peter Boughton Avatar answered Jul 13 '26 11:07

Peter Boughton