After some initial learning about XML and handling it in ColdFusion 6.1 & 7, I came to the conclusion that ColdFusion wasn't the best when it came to XML.
When reading and transforming XML, ColdFusion does a great job and is at its usual brilliantly quick. Where I think it gets cumbersome is in maintenance scenarios where you have to edit a given XML file. For example, you may have some XML that is being used as the sole data source and needs updating whenever a user adds item x or deletes item z, etc.
An ideal solution to this is to use XPath to quickly navigate the XML in readiness for your CRUD operations. ColdFusion's XMLSearch() method is not suitable in this case however, as it only returns data from an XPath query. To navigate the XML using XPath, we need the XPath query to return a nodeset that is a collection of pointers to the original data. Once we have this collection of pointers, we can go about performing our CRUD operations on the data.
This is where BetterXML comes in. BetterXML is a set of two ColdFusion Components; an XML reader and an XML editor, the editor extending the reader. They both use the org.apache.xpath.XPathAPI java object that lets them quickly navigate the data using XPath.
The public methods are as follows:
XML Reader:
- Init( src ) - Returns an instance of the object, loading the XML if supplied
- Load( src ) - loads XML from either an xml string, file or URL
- Search( XPath, filter ) - returns an array of either strings or simplified structures based on the results of the XPath query
- Count( XPath ) - returns the number of results returned by the XPath query
- Names( XPath ) - returns the names of the attributes and elements returned by the XPath query
- XML() - returns the XML as a string
- Init( src ) - Returns an instance of the object, loading the XML if supplied
- Write( destination ) - Writes the XML to file
- CreateElement( XPath, Name, Value ) - Creates an element in all the parents returned by the XPath query. The value of the element can be a simple value or a structure to write nested elements.
- CreateAttribute( XPath, Name, Value ) - Creates an attribute in all the elements returned by the XPath query
- Update( XPath, Value ) - Updates all the elements returned by the XPath query. The updated value can be a simple value or a structure to write nested elements.
- Delete( XPath ) - Deletes all the elements returned by the XPath query
Lets say you have a huge XML file that is full of comments that are now redundant. To delete all the comments from the file we can do:
<cfinvoke component="BetterXML_Editor" method="init" src="#myFile#" returnVariable="xmlFile"/>
<cfscript>
xmlFile.Delete('//comment()');
xmlFile.Write(myFile);
</cfscript>
The code is minimal and the load times hugely improved when compared to using native ColdFusion functions to achieve the same end :)
Dom
8 comments:
great stuff Dom, CF really needs this, it is as you say very lacking on the xPath front. I wish I have found this a few months back when I was struggling to work with SOAP packets.
Cheers Russ. I'm glad; being a relative noob I was worried that there was something I was missing that meant it wasn't worth the gargantuan effort (although the stuff learned on the way would be worth it regardless)! ;)
Do you have Unit Testing for this component?
No, though it would be a good idea. Why do you ask?
Awesome stuff, thanks so much. Are any of these improvements tied up in CF8 or 9? Thanks man! Hope to use it in my next project!
Sean
www.thejumpstarter.com
Hey Sean, glad you like it :) CF8 did not bring about any developments along these lines and AFAIK CF9 has not either - I stand poised to be corrected on that though.
this looks like something would be very useful to me. has it been tested on Railo?
No, it hasn't been tested in Railo. It is highly likely that it will not work as it makes use of the underlying Xml implementation in ColdFusion which I know is different in BlueDragon at least (at the time of making Better Xml I was unaware of Railo).
Should be quick enough to test though (especially if it does not work :| ).
Post a Comment