A Simple XML Component
Posted on Mar 30, 2005
The code that I am posting here forms the basis for a ColdFusion Component to maintain an employee list in XML. This comes from a project at work which does something a little more logical than maintain an employee list in XML (but I cannot share the original code). However, this can be useful for a number of projects and therefore I am posting a generalized version of the code for anyone to use.The basics of the component are that it adds employees (with attributes) to a simple xml object. It allows you to edit a particular item, delete a particular item and convert the entire xml object into a query. All of this is done using a unique employeeID for simplicity, but you could modify this application to be more robust (and create additional components to persist the xml somehow as well). Enough said...here is the code:
<cffunction name="init" access="public" output="false" returntype="employee">
<cfargument name="xmlString" type="string" required="false">
<cfscript>
// parse the xml if an existing was supplied if (isDefined("arguments.xmlString")) {
variables.empStruct = xmlParse(xmlString);
}
// if not, create the empty xml structure else {
variables.empStruct = xmlNew();
variables.empStruct.xmlRoot = xmlElemNew(empStruct,"employees");
}
return this;
</cfscript>
</cffunction>
<cffunction name="addItem" access="public" output="false" returntype="void">
<cfargument name="employeeID" type="string" required="true">
<cfargument name="lastName" type="string" required="false" default="">
<cfargument name="firstName" type="string" required="false" default="">
<cfargument name="xmlText" type="string" required="false" default="">
<cfargument name="dateAdded" type="date" required="false" default="#now()#">
<cfscript>
var i = 0;
// search to see if that employeeID already exists var objItemToAdd = xmlSearch(variables.empStruct,"//employee[@EMPLOYEEID='#arguments.employeeID#']"); // if the item does not already exist, add it if (arrayLen(objItemToAdd) EQ 0) {
// append the child element and populate the attributes and xmltext arrayAppend(variables.empStruct.employees.XmlChildren,XmlElemNew(empStruct,"employee"));
i = arrayLen(variables.empStruct.employees.XmlChildren);
variables.empStruct.employees.XmlChildren[i].xmlAttributes.lastName = arguments.lastName;
variables.empStruct.employees.XmlChildren[i].xmlAttributes.firstName = arguments.firstName;
variables.empStruct.employees.XmlChildren[i].xmlAttributes.employeeID = arguments.employeeID;
variables.empStruct.employees.XmlChildren[i].xmlAttributes.dateAdded = arguments.dateAdded;
variables.empStruct.employees.XmlChildren[i].xmlText = arguments.xmlText;
}
</cfscript>
</cffunction>
<cffunction name="editItem" access="public" output="false" returntype="void">
<cfargument name="employeeID" type="numeric" required="true">
<cfargument name="lastName" type="numeric" required="false">
<cfargument name="firstName" type="string" required="false" default="">
<cfargument name="xmlText" type="string" required="false">
<cfargument name="dateAdded" type="date" required="false">
<cfscript>
// search according to employeeID var objItemToEdit = xmlSearch(variables.empStruct,"//employee[@EMPLOYEEID='#arguments.employeeID#']"); // if edits were supplied to the attributes, set them if (isDefined("arguments.lastName")) {
objItemToEdit[1].xmlAttributes.lastName=arguments.lastName;
}
if (isDefined("arguments.firstName")) {
objItemToEdit[1].xmlAttributes.firstName=arguments.firstName;
}
if (isDefined("arguments.xmlText")) {
objItemToEdit[1].xmlText=arguments.xmlText;
}
if (isDefined("arguments.dateAdded")) {
objItemToEdit[1].xmlAttributes.lastName=arguments.dateAdded;
}
</cfscript>
</cffunction>
<cffunction name="deleteItem" access="public" output="false" returntype="void">
<cfargument name="employeeID" type="numeric" required="true">
<cfscript>
// search for the item to delete and then clear it var objItemToDelete = xmlSearch(variables.empStruct,"//employee[@EMPLOYEEID='#arguments.employeeID#']"); arrayClear(objItemToDelete[1]);
arrayDeleteAt(objItemToDelete, 1);
</cfscript>
</cffunction>
<cffunction name="toQuery" access="public" output="false" returntype="query">
<cfscript>
var i = 0;
// create the empty query var returnQry = queryNew("employeeID,lastName,firstName,dateAdded,comments");
// loop through the xml elements and use their values to populate the query rows for (i=1;i LTE arrayLen(variables.empStruct.employees.XmlChildren);i=i+1) {
queryAddRow(returnQry);
querySetCell(returnQry,"employeeID",variables.empStruct.employees.XmlChildren[i].xmlAttributes.employeeID);
querySetCell(returnQry,"lastName",variables.empStruct.employees.XmlChildren[i].xmlAttributes.lastName);
querySetCell(returnQry,"firstName",variables.empStruct.employees.XmlChildren[i].xmlAttributes.firstName);
querySetCell(returnQry,"dateAdded",variables.empStruct.employees.XmlChildren[i].xmlAttributes.dateAdded);
querySetCell(returnQry,"comments",variables.empStruct.employees.XmlChildren[i].xmlText);
}
return returnQry;
</cfscript>
</cffunction>
<cffunction name="getEmpStruct" access="public" output="false" returntype="xml">
<cfreturn variables.empStruct>
</cffunction>
</cfcomponent>
Here is a basic page that shows how you might use the methods supplied within the component to create your employee list:
<cfsetting showdebugoutput="false">
<cfsavecontent variable="testXml"><?xml version="1.0" encoding="UTF-8"?><employees><employee DATEADDED="{ts '2005-03-29 14:02:54'}" LASTNAME="Rinaldi" FIRSTNAME="Rinaldi" EMPLOYEEID="99999">this employee was added during initialization</employee></employees></cfsavecontent>
<cfscript>
// test the init with xml from above to prepopulate objWL = createObject("component","employee").init(testXml);
// test add employees objWL.addItem(11111,"Hicks","Shannon");
// test adding the same employee twice (should only add one) objWL.addItem(11111,"Hicks","Shannon");
objWL.addItem(22222,"Pease","Shannon","freedom fries");
objWL.addItem(98979,"Feyrer","Chris","this employee will be deleted");
// test edit item objWL.editItem(employeeID=98979,xmlText="this employee has been edited");
// test delete an item objWL.deleteItem(22222);
</cfscript>
<cfdump var="#objWL.getEmpStruct()#">
<cfdump var="#objWL.toQuery()#">
<cfabort>
As usual, hopefully this is useful to someone (as it once would have been to me!). Enjoy!
Comments
So, what would the form-side of this look like?
Posted By johnny / Posted on 01/05/2006 at 1:34 PM
There really isn't anything special about the form for this...just a standard form would work. You would do your validation and then (if everything is ok) do something like objWL.addItem(form.id,form.lastName,form.firstName,form.description);
Posted By Brian Rinaldi / Posted on 01/09/2006 at 8:53 PM