barscribe.com

In the spirit of Andy Jarrett's Friday jokes, which I really enjoy by the way, I thought I'd share a site my good friend Greg Steen launched over the summer, barscribe.com. I love the idea, unfortunately as a new father I haven't yet had the chance to contribute any barscribe wisdom myself. There's not a whole lot there yet, but what is there is pretty funny so check it out if you get a chance. Or better yet contribute, I'm sure Greg would appreciate it.

WARNING: If you are easily offended you had better stay away as the site does involve "toilet humor."

Working with XML Namespaces in XSL Stylesheets

One of the things I like about working on a larger team is that there is plenty of opportunity to bounce questions off of co-workers and, as anyone who has ever answered a question on a forum or mailing list can tell you, you often learn as much trying to answer a question as you do by asking one.

This happened to me last week when a co-worker came to me with a question about XSLT. He had an XML document that looked something like the following:

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" SOAP-ENV:encodingStyle="">
<SOAP-ENV:Header xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
...
</SOAP-ENV:Header>
<SOAP-ENV:Body xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<QueryResults xmlns="http://schemas.mischefamily.com">
<People xmlns="http://schemas.mischefamily.com">
<Person personId="12345" xmlns="http://schemas.mischefamily.com">
<PersonalData>
<Contact>
<StructuredName>
<GivenName>Nathan</GivenName>
<MiddleName></MiddleName>
<FamilyName>Mische</FamilyName>
</StructuredName>
</Contact>
</PersonalData>
</Person>
</People>
</QueryResults>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

He wanted to transform it into:

<People>
<Person>
<FirstName>Nathan</FirstName>
<LastName>Mische</LastName>   
</Person>
</People>

He had the beginnings of an XSL stylesheet which had the SOAP-ENV namespace declared in the xsl:styleheet root element, but his search sting, "//SOAP-ENV:Body/QueryResults/People", wasn't returning any results. Just looking at the original XML document I knew the problem had something to do with namespaces, but I wasn't quite sure how to handle the namespaces defined in the QueryResults, People, and Person nodes. Turns out that the answer was fairly simple; we just needed to declare another prefixed namespace in the stylesheet root element pointing to http://schemas.mischefamily.com.

<?xml version="1.0" encoding='utf-8' ?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:MISCHE="http://schemas.mischefamily.com">

<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<People xsl:exclude-result-prefixes="SOAP-ENV MISCHE">
<xsl:for-each select="//SOAP-ENV:Body/MISCHE:QueryResults/MISCHE:People"> <Person>
<FirstName><xsl:value-of select="./MISCHE:Person/MISCHE:PersonalData
/MISCHE:Contact/MISCHE:StructuredName/MISCHE:GivenName"
/>
</FirstName>
<LastName><xsl:value-of select="./MISCHE:Person/MISCHE:PersonalData
/MISCHE:Contact/MISCHE:StructuredName/MISCHE:FamilyName"
/>
</LastName>
</Person>
</xsl:for-each>
</People>
</xsl:template>
</xsl:stylesheet>

There were a few things, however, that threw me for a loop while coming up with this stylesheet. First, I originally thought that PersonalData and all the nodes below it were in the local namespace because everything above that node (QueryResults, People, Person) had a xmlns attribute defined. Based on this assumption my first xsl:value-of select statement for the transformed FirstName node looked like "./MISCHE:Person/PersonalData/Contact/StructuredName/GivenName". The problem was this statement didn't return anything. After some quick research I realized this was because the namespace declared in the xmlns attribute is inherited. This meant that all of the elements below the Person element in the source XML were also in the http://schemas.mischefamily.com namespace and needed to be prefixed with MISCHE in the select statements of my stylesheet. As a side note, to make my original query work you would need to force child nodes back into the local namespace, which you can do if you can give the xmlns attribute an empty value like so:

...
<QueryResults xmlns="http://schemas.mischefamily.com">
<People xmlns="http://schemas.mischefamily.com">
<Person personId="12345" xmlns="http://schemas.mischefamily.com">
<PersonalData xmlns="">
<Contact>
<StructuredName>
<GivenName>Nathan</GivenName>
<MiddleName></MiddleName>
<FamilyName>Mische</FamilyName>
</StructuredName>
</Contact>
</PersonalData>
</Person>
</People>
</QueryResults>
...

The second issue I had was that my original stylesheet was returning the SOAP-ENV and MISCHE namespace declarations in the root node of my result. To suppress the namespaces in my results I had to add the exclude-result-prefixes attribute to the Person element in my XSL stylesheet.

Anyway, these were just some things I though I'd share in case you find yourself trying to transform XML with a different namespaces defined.

SELECT * and cfqueryparam

I've been using cfqueryparam for some time for both its performance and security benefits, but today I ran into something new with this tag. (I should state that this behavior was observed and confirmed using CFMX 7 and SQL Server 2000.) It all started with a question from a friend about some strange behavior he was seeing with a query which used cfqueryparam. He had added columns to a table, but his query against this table was not returning these new columns. The query in question used a wildcard select with cfqueryparam so it looked something like:

<cfquery name="myQuery" datasource="myDSN">
SELECT *
FROM myTable
WHERE myTableID = <cfqueryparam value="#x#" cfsqltype="cf_sql_numeric" />
</cfquery>

I suspected it had something to do with the caching of the execution plan, which most databases will do if you use bound parameters, and it turns out I was correct. To explain the issue lets say we start with a table with two columns. The first time we run this query in a ColdFusion template the database compiles and caches the execution plan for the query. If you add a column and run the template again the query will still only return our first two columns because the database uses its cached execution plan. Because the query uses the star wildcard and the plan was compiled before the third column was added to the table the cached plan only knows about our first two columns and completely ignores our new third column.

Now there are several ways around this issue. First don't use wildcard select statements. I generally list all the columns I want to return in my select statement, which may explain why I haven't run into this issue before, but I'll admit that there may be times when this just isn't practical. In those situations you can either not use cfqueryparam or use SET FORCEPLAN to force SQL Server to recompile the execution plan like so:

<cfquery name="myQuery" datasource="myDSN">
SET FORCEPLAN ON;
SELECT *
FROM myTable
WHERE myTableID = <cfqueryparam value="#x#" cfsqltype="cf_sql_numeric" />;
SET FORCEPLAN OFF;
</cfquery>

One other thing I didn't realize is that execution plan reuse is tied to the database connection, so if you restart ColdFusion after adding your new column you should get the expected results.

Anyway, just something to watch out for, especially since many of the examples I've seen for using queryparam use SELECT * and don't mention this behavior.

Another note on the FarCry 3.0.2 RC

Another quick note on installing the FarCry 3.0.2 RC package. Many of the rule component tags in farcry_core\packages\rules have hint attributes which span multiple lines. For example ruleNews.cfc looks like this:

<cfcomponent displayname="News Rule" extends="rules"
   hint="News rule publishes news content items in date order, with
      most recently published first. News content is only visible
      if it is a) approved content; b) time is past the publish date;
      c) time is before the expriy date, and; d) it matches the nominated
      categories."
>

While ColdFusion doesn't have a problem with this, it does cause problems with the JavaScript generated in \farcry_core\admin\includes\editcontiner_js.cfm. One fix is to just remove the line breaks from the hint attribute in the rules. This is what I did because at the time I discovered this error I didn't feel like tracking down where the JavaScript was being generated. Another, and probably the better, approach is to strip the line breaks out when building the JavaScript.

<!--- editcontainer_js.cfm line 130 --->

oRules['#qRules.rulename#'].hint = '#REReplace(application.rules[qRules.rulename].hint,"\r\n"," ","ALL")#';

Note that I haven't test the above code but I think it should work.

Update

So after I posted this I went over to the FarCry bug database to log this issue. Apparently this is something I should have done first because it has already been reported and fixed:

Configure Rules does not allow available rule types to be moved to active rule types

The fix uses a the JSStringFormat function, a function I really haven't used all that often. (OK, maybe never.) I'll have to look into exactly what this function does as it sounds like it could come in pretty handy, especailly given all the AJAX stuff I've been doing lately.

FarCry Blog Objects

For the past month or so I've been running a small intranet site on FarCry. I've been using this site for project notes, basically just posting my ideas and discoveries as standard FarCry news items for my co-workers to review. I plan to expand the site to contain documentation and other content related to the project I'm working on, but for now it's fairly basic.

So the news items are working well to add transparency to my development process, but I really want to get some feedback from my co-workers on some of my ideas. To do this I wanted to allow comments to be added to news items. Sound like a blog? Well it did to me, so I decided to create some basic blog content objects for FarCry.

Note that I built these objects using the 3.0.2 RC of FarCry with the mollio skin. I haven't done much testing so use at your own risk! That said, to install the blog:

  1. Download the farcry_mollio_blog.zip and unzip it to your project directory.
  2. Reload your FarCry application by browsing to your FarCry site and adding updateapp=1 to the url parameters
  3. Login to the FarCry administrator and deploy the four new objects: nmBlogEntry, nmBlogComment, ruleBlogEntries, and ruleBlogComments.
  4. Add a page to your FarCry site for the blog.
  5. Add your first blog entry under Content -> Blog.
  6. Add the nmBlogEntries rule to the bottom container on the blog page.
  7. View the blog entry and add the nmBlogComments rule to the blogBottom container.

There is still a lot of work I want to do with these objects. For example there is no way to manage comments. In fact there is absolutely no way to know comments have been added without looking at the blog entry. I'd also like to add a calendar view and a category listing. It all depends on how much time I have and how much interest people show in these objects.

If you do decide to give these components a try please let me know how it goes.

Installing FarCry 3.0.2 Release Candidate

I had a few problems getting the FarCry 3.0.2 Release Candidate installed today so I thought I'd share what I did to get it up and running. I was trying to install from the farcry-milestone_3-0-2RC_r286.zip, available from the FarCry downloads page. I was following the installation guide, but I kept getting errors while running the installer. I decided to ignore the errors and see if I could view the site or login to the FarCry administrator. I couldn't. After a little digging I was able to determine that the installation files included in the zip expect to use the older pliant webskin, while the download includes the more recent mollio webskin. To get the installation to run I had to make changes to a couple of templates.

farcry_core/admin/install/index.cfm

  • Line 105: change farcry_pliant to farcry_mollio

farcry_core/admin/install/_createDefaultNodes.cfm

  • Line 15: change displayPageLanding to displayPageTypeA
  • Line 39: change displayPageLanding to displayPageTypeA

After making these changes I was able to run the installer and updates to get a working FarCry site. Note that I still got errors running the installer and updates, but everything seems to be installed correctly.

Calculating Image Dimensions

Yesterday I needed to get the dimensions of an uploaded image. I was just about to open up the Java API docs when I found this post over on Eddie Awad's Blog. So I know this is nothing new, but here is the method I wrote for my service. Note I'm passing in an ImageBean component and calling it's setWidth and setHeight methods once I have the dimensions.

<cffunction name="getDimensions" ... >
   <cfargument name="ImageBean" ... />

   <cfset var width = 0 />
   <cfset var height = 0 />
   <cfset var toolkit = "" />
   <cfset var image = "" />

   <cftry>
      <cfset toolkit = CreateObject("java","java.awt.Toolkit") />
      <cfset image = CreateObject("java","java.awt.Image") />
      <cfset image = toolkit.getDefaultToolkit().getImage(arguments.ImageBean.getFilePath()) />

      <cfset width = image.getWidth() />
      <cfset height = image.getHeight() />
      <cfset image.flush() />

      <cfcatch type="any">
         <cfset width = 0 />
         <cfset height = 0 />
      </cfcatch>         
   </cftry>

   <cfset arguments.ImageBean.setWidth(width) />
   <cfset arguments.ImageBean.setHeight(height) />
         
</cffunction>

XML Notepad 2006

A coworker sent me a link to Microsoft's XML Notepad 2006 today. According to the download page, "XML Notepad 2006 provides a simple intuitive user interface for browsing and editing XML documents."

I downloaded it just to give it a quick try. It opens XML files in a tree view, similar to Eclipse's default XML editor. It also looks like it can do XSL transformations, but I couldn't get this to work. (To be fair I really didn't try that hard, I just wanted to see what the tool looked like.)

Anyway, some people may find this tool useful, but as I'm an Eclipse user I think I'll stick with XMLBuddy for now.

Lighthouse Pro

I first gave Ray Camden's Lighthouse a try a few years ago when it was released on a DRK. I didn't end up using it at the time because I remember thinking that as my project grew the XML storage engine could become an issue. Since then I've used several commercial bug trackers including ProblemTracker and JIRA and currently my company is using a home grown issue/request tracking system.

Well, we recently started a fairly large project at work but I didn't want to use our in house issue tracking system as it generates several notifications and requires managers to route issues. While we will eventually move this project into our in house system, at this early stage of development it really didn't seem appropriate. So I decided to give Ray's Lighthouse another try, this time in the form of Lighthouse Pro. I have to say I'm really impressed. I downloaded the package and had the bug tracker up and running in less than 10 minutes. Best of all our team now has full control over our own bug database which should help speed up development and keep us from annoying everyone else in the company with all of our bugs. Not that we ever write any buggy code mind you.

BlogCFC was created by Raymond Camden. This blog is running version 5.8.001.