I love XSL!
I have been fighting with recursion for ages now and have found it to always be a real problem effecting performance, quite often you have to use complicated caching techniques, until now!
Using XSL you can perform recursion techniques on flat XML data. It sounds complicated but really it isn’t.
Say you have node data like the following (in a flat structure).
<tree>
<node icon="" id="1" objectID="9" parentID="0" recordID="15" ref="sites" title="Sites"/>
<node icon="" id="2" objectID="9" parentID="0" recordID="28" ref="media" title="Template Media"/>
<node icon="" id="3" objectID="9" parentID="0" recordID="31" ref="templates" title="Templates"/>
<node icon="site.png" id="4" objectID="11" parentID="1" recordID="1" ref="refresh--test" title="Refresh"/>
<node icon="page.png" id="5" objectID="1" parentID="4" recordID="134" ref="home" title="Home"/>
<node icon="form.png" id="6" objectID="12" parentID="5" recordID="60" ref="enq_form" title="Enquiry Form"/>
<node icon="form.png" id="7" objectID="12" parentID="5" recordID="61" ref="site_review" title="Site Review"/>
<node icon="menu.png" id="11" objectID="5" parentID="4" recordID="8" ref="topnav" title="Top Nav 2"/>
<node icon="" id="12" objectID="9" parentID="0" recordID="33" ref="users" title="Users"/>
</tree>
Using XSL you can build a hierarchical tree from this data:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0"> <xsl:template match="tree">
<!-- Starts the tree -->
<ol>
<xsl:apply-templates/>
</ol>
</xsl:template>
<!-- Selects root nodes -->
<xsl:template match="//node[@parentID=0]"> <xsl:call-template name="process-branch">
<xsl:with-param name="id"><xsl:value-of select="@id"/></xsl:with-param>
<xsl:with-param name="parentID"><xsl:value-of
select="@parentID"/></xsl:with-param>
</xsl:call-template> </xsl:template> <!-- Recursive function -->
<xsl:template name="process-branch">
<xsl:param name="id"/>
<xsl:param name="parentID"/> <xsl:choose>
<!-- If element has no sub-nodes -->
<xsl:when test="count(//node[@parentID=current()/@id])=0">
<!-- Writes the node -->
<li>
<a href="" mce_href=""><xsl:value-of select="@title" /></a>
</li>
</xsl:when>
<!-- If element has sub-nodes-->
<xsl:otherwise>
<!-- Starts a node with children element -->
<li>
<a href="" mce_href=""><xsl:value-of select="@title" /></a>
<ol>
<!-- For every sub-nodes of current node -->
<xsl:for-each select="//node[@parentID=current()/@id]">
<!-- Recurse the branch processing -->
<xsl:call-template name="process-branch">
<xsl:with-param name="id"><xsl:value-of
select="@id"/></xsl:with-param>
<xsl:with-param name="parentID"><xsl:value-of
select="@parentID"/></xsl:with-param>
</xsl:call-template>
</xsl:for-each>
</ol>
</li>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
Obviously you can replace the html with whatever elements you wish, even build hierarchical XML.
You then use the (rather handy) coldfusion function
#XMLTransform(XMLParse(xmldata), xslSheet)#
And there you have it, no long loops with recurring queries!
Finding an e-commerce package
About 4 months ago we purchased a license for a coldfusion e-commerce software package, but only now am I finding functionality missing that I assumed would be there. For example the system allows you to enter discounts, but it doesn’t cater for “buy x get x free” and today a customer wanted to know how many customers they had. I went to reporting and couldnt find a report for this simple piece of information. I had to do a search on the customers and read how many results were returned. Not ideal.
I think it’s very hard to think about all the functionality you require when you are buying an e-commerce solution. It’s also hard to find something that does everything you want but doesn’t cost too much per-license. Most people who are looking to start a shop don’t often have a lot to spend and they see advertisements like “E-commerce solution £9.99 a month” which makes them question why they have to pay such a hefty price tag for your solution.
I’d love to hear your thoughts and If you have any recommendations for any other software packages.
Blog CFC customization
I don’t know if any of you have used Blog CFC but it’s a great little app. I have been implementing it into our CMS. I have found a few problems with it though, for example if you want the admin completely seperate in a different folder structure it’s very hard to get the links to work.
I also didnt really like the calendar aspect of the tool so I have written my own “pod” for just showing the months and years with posts.
in the blog.cfc i have written the following function:
<cffunction name="getActiveMonths" returnType="query" output="false" hint="Returns a query of months and years with Entries.">
<cfargument name="year" type="numeric" required="false">
<cfset var months = "">
<cfset var posted = ""> <cfif instance.blogDBType is "MSSQL">
<cfset posted = "dateAdd(hh, #instance.offset#, tblblogentries.posted)">
<cfelseif instance.blogDBType is "MSACCESS">
<cfset posted = "dateAdd('h', #instance.offset#, tblblogentries.posted)">
<cfelseif instance.blogDBType is "MYSQL">
<cfset posted = "date_add(posted, interval #instance.offset# hour)">
<cfelseif instance.blogDBType is "ORACLE">
<cfset posted = "tblblogentries.posted + (#instance.offset#/24)">
</cfif>
<cfquery datasource="#instance.dsn#" name="months" username="#instance.username#" password="#instance.password#">
select distinct
<cfif instance.blogDBType is "MSSQL">
datepart(mm, #preserveSingleQuotes(posted)#)
<cfelseif instance.blogDBType is "MYSQL">
extract(month from #preserveSingleQuotes(posted)#)
<cfelseif instance.blogDBType is "MSACCESS">
datepart('m', #preserveSingleQuotes(posted)#)
<cfelseif instance.blogDBType is "ORACLE">
to_char(#preserveSingleQuotes(posted)#, 'mm')
</cfif> as posted_month,
<cfif instance.blogDBType is "MSSQL">
datepart(yyyy, #preserveSingleQuotes(posted)#)
<cfelseif instance.blogDBType is "MYSQL">
extract(year from #preserveSingleQuotes(posted)#)
<cfelseif instance.blogDBType is "MSACCESS">
datepart('y', #preserveSingleQuotes(posted)#)
<cfelseif instance.blogDBType is "ORACLE">
to_char(#preserveSingleQuotes(posted)#, 'yyyy')
</cfif> as posted_year
from tblblogentries
where
blog = <cfqueryparam value="#instance.name#" cfsqltype="CF_SQL_VARCHAR" maxlength="50">
and #preserveSingleQuotes(posted)# < <cfqueryparam cfsqltype="cf_sql_timestamp" value="#blogNow()#">
and released = 1
ORDER BY posted DESC
</cfquery> <cfreturn months>
</cffunction>
Then in the front end in the calendar.cfm pod I commented out the calendar and put in the following code:
<cfscript>
monthsQuery=application.blog.getActiveMonths();
</cfscript>
<ol>
<cfoutput query="monthsQuery">
<li><a href="#application.rooturl##posted_year#/#posted_month#" mce_href="#application.rooturl##posted_year#/#posted_month#">#monthAsString(posted_month)# #posted_year#</a></li>
</cfoutput>
</ol>
It seems to work a treat!
Coldfusion 8 security
An independant source has released a report on the security of the new version of Coldfusion, with the conclusion being “ColdFusion 8 exhibits a high degree of resilience to application layer attacks with no compromise on functionality provisioned by the new features.”
There is also mention of the new Authentication and Authorization model ( you can now have more than one login for the coldfusion administration) and that it has raised the security of the overall product.
Here is the report http://www.dcooper.org/ColdFusion_8_Product_Security_Brief.pdf