Third Person

Nick Dunn is a lead front-end developer at Airlock, a digital creative agency in Shoreditch, London. He is passionate about accessibility, user experience and code-indenting. He recently played ElbowForget Myself.

First Person

I like to bookmark things that interest me. I also like to plan things, take photos of things I see, and tap my feet to a groove. I sometimes write tiny messages, and longer ones too. I have an online CV and a collection of links that are and aren't about me.

Export a CSV report from Sifter issues

30th June 2009, 0 comments , tagged with Sifter offers a super-smooth user experience for tracking bugs and issues, but no exporting?

The Sifter API has been a long time coming and there’s nothing on the horizon yet. I recently embarked on my own set of scripts to automate the process of creating a report from Sifter. The idea is to parse the issues HTML list into XML and then transform to whatever the user desires using XSLT (a printable HTML page, an XML file, a CSV). But I digress.

So I found a natty little update to Sifter that provides native export of your issue list as a CSV file!

Spot /issues?s=... in the URL and change it to /issues.csv?s=. Tada!

I’ll hold out for the API.

Show latest Last.fm plays on your Symphony site

10th June 2009, 0 comments , tagged with , , , Symphony has a hunger for XML. Thankfully Last.fm’s API shares this appetite.

At the top of my blog I have added the name of the last track scrobbled to Last.fm. Symphony made this so easy, eating a biscuit with a fresh brew after five minutes. Here’s how:

First you need a Last.fm user account, and one of the various applications to scrobble your tracks from iTunes (or Windows Media Player, if your life is broken). Then you need to grab an API key. The key will be a hash that looks something like this (note: this is not my real API key!).

3d21e002930b853d2f048e517c577ec7

You can then create a URL using the Last.fm API to return your recent tracks as XML. We will use the user.getRecentTracks method of the API. Your URL should be in this format:

http://ws.audioscrobbler.com/2.0/?method=user.getrecenttracks&user={your-username}&api_key={your-api-key}

Log in to your Symphony site and create a new Data Source, choosing “Dynamic XML” as its source. Paste your API call URL into the URL field and update the cache value to something small, between 1 and 10 minutes should do.

Figure 1. Last FM Data Source Figure 1. Last FM Data Source

Note that I have also added the XPath expression //track[1] so that only the first track node is included in my Page to keep things lean.

Attach this Data Source to your Page and fire up ?debug to check you can see the fresh track node. You can? Great! I’m glad you’ve been keeping up.

Figure 2. Last FM Data Source debug XML Figure 2. Last FM Data Source debug XML

All you need now is a little XSLT magic to write this content into your page. Where you want the track name to appear, add a template match to the track node above:

<xsl:apply-templates select="/data/last-fm/track" mode="last-fm"/>

And neatly out of the way you can create a template to handle the rendering of the content. My template looks like this. Notice I’m checking whether the track has a nowplaying attribute and changing the label accordingly.

<xsl:template match="track" mode="last-fm">

    <xsl:choose>
        <xsl:when test="@nowplaying='true'">
            <xsl:text>Currently listening to </xsl:text>
        </xsl:when>
        <xsl:otherwise>
            <xsl:text>Recently listened to </xsl:text>
        </xsl:otherwise>
    </xsl:choose>

    <xsl:value-of select="concat(name, ' by ', artist)"/>

</xsl:template>

How stupendously easy!

The kettle’s boiled. Time for a cuppa.

Hanging Out With Humans

10th June 2009, 0 comments , tagged with Data.Select.Party are a party-math-indie quartet from London. And this is their album.

Party. Data Select Party — Hanging Out With Humans Party. Data Select Party — Hanging Out With Humans

Data.Select.Party are difficult to describe. They combine the smiles of Tellison, the tapped clean guitars of This Town Needs Guns, and the yelps and chants of Dartz! and Foals. I’ve seen them play a few times in and around London, and Hanging Out With Humans is a fine collection of new material and several old favourites too.

Indiemo kids rejoice! There be cowbells.

Buy it on iTunes now.

Developing with Symphony using the Firebug console

9th June 2009, one comment , tagged with , Symphony provides powerful debugging and performance profiling pages by appending various URL parameters to pages. No longer. Firebug is all you need.

With some magic from the FirePHP library, Symphony development just got a whole lot easier. Instead of having to append ?debug or ?profile to the end of a URL to view debug XML and performance profiles, you can now have this information sent directly to your Firebug console!

My Firebug Profiler extension provides:

  • quick access to page lifecycle profiler
  • query counts for all Data Sources
  • optional XML fragments for each Event and Data Source on the page

Firebug Profiler source on Github

Firebug Profiler

An alternative 'for' loop using XSLT and template callbacks

20th May 2009, one comment , tagged with , XSLT 1.0 has no native way of achieving a for loop, without iterating through XML. Until now.

XSLT is planted firmly in the declarative programming style — something that regularly frustrates newcomers from procedural languages such as PHP or JavaScript. You need to change your programming mindset to approach familiar concepts in new ways. One such example is the traditional for loop. In XSLT there exists a for-each element which iterates over an XML nodeset:

<xsl:for-each select="countries/country">
    <xsl:value-of select="text()"/>
</xsl:for-each>

As dandy as this is, it relies on having XML to iterate over. How can you achieve a for loop to provide, say, ten iterations, from 1 to 10. In PHP this would be a simple as:

for($i=1; $i<=10; $i++) {
    echo($i);
}

To achieve this using XSLT you need to take a different approach. Below I’ll outline two ideas — one a simple hack, the other more advanced and elegant — for generating a for loop using XSLT 1.0.

1. Tokens at the ready

Using the tokenize() function of the EXSLT strings library one can break a string of a given length into individual characters and loop through each:

<xsl:for-each select="str:tokenize('..........')/token">
    <xsl:value-of select="position()"/>
</xsl:for-each>

There are then full-stops in the string, meaning that ten token nodes will be created. Not particularly elegant or maintainable. This can be improved on slightly by generating the string dynamically, making it easier to change its length:

<xsl:for-each select="str:tokenize(str:padding(10,'.'))/token">
    <xsl:value-of select="position()"/>
</xsl:for-each>

The padding() function creates a string of a given length.

2. Recursive to the max

The more ‘XSL-like’ approach is to use a recursive call-template to execute the iteration. The template is supplied with start and end conditions and repeatedly calls itself until the end condition is met. The finest explanation I’ve seen is Loop with recursion in XSLT on IBM developerWords. Recommended reading.

Writing a recursive template to achieve the above requirement is relatively trivial:

<xsl:template name="for-loop">
    <xsl:param name="count" select="1"/>

    <xsl:if test="$count > 0">
        <xsl:value-of select="$count"/>
        <xsl:call-template name="for-loop">
            <xsl:with-param name="count" select="$count - 1"/>
        </xsl:call-template>
    </xsl:if>

</xsl:template>

The problem here is that the template output is muddled into the same template as the iteration/recursion logic. It would make more sense to have a single “iterator” template to perform the recursion, and have the output rendered in a separate template. Consider the following scenario:

You’re building a form and need to fill a select drop down with ten options (1–10), but you also need to render five checkboxes. Using the above example you would need to replicate the template twice, naming them select-loop and checkbox-loop. Inside each respective template you would change the output to return either an <option> element or a checkbox.

My colleague Paul Garrett and I have devised a cunning way for a call-template to execute a callback template which is where the custom rendering is achieved.

Consider this markup to render a select box with ten options, followed by five checkboxes:

<xsl:template match="data"> 

    <select>
        <xsl:call-template name="iterator">
            <xsl:with-param name="iterations" select="'10'"/>
            <xsl:with-param name="callback" select="'render-option'"/>
        </xsl:call-template>
    </select>

    <xsl:call-template name="iterator">
        <xsl:with-param name="iterations" select="'5'"/>
        <xsl:with-param name="callback" select="'render-checkbox'"/>
    </xsl:call-template>

</xsl:template>

<xsl:template match="render-option" mode="iterator-callback">
    <xsl:param name="position"/>
    <option>
        <xsl:value-of select="$position"/>
    </option>
</xsl:template>

<xsl:template match="render-checkbox" mode="iterator-callback">
    <xsl:param name="position"/>
    <input type="checkbox" name="fields[checkbox-{$position}]"/>
</xsl:template>

We can call a generic iterator template passing the number of iterations required (as you would a traditional for loop) while providing the name of a callback template. The iterator template creates an XML node of the same name and selects it using an apply-templates. The callback template is passed the position in the loop providing context.

The full iterator template:

<xsl:template name="iterator">
    <xsl:param name="start" select="'1'"/>
    <xsl:param name="iterations" select="$iterations"/>
    <xsl:param name="direction" select="'+'"/>
    <xsl:param name="callback"/>
    <xsl:param name="callback-params"/>

    <xsl:param name="count" select="$iterations"/>

    <xsl:if test="$callback and $count > 0">

        <xsl:variable name="position">
            <xsl:choose>
                <xsl:when test="$direction='-'"><xsl:value-of select="$start - ($iterations - $count)"/></xsl:when>
                <xsl:otherwise><xsl:value-of select="$start + ($iterations - $count)"/></xsl:otherwise>
            </xsl:choose>
        </xsl:variable>

        <xsl:variable name="callback-node">
            <xsl:element name="{$callback}">
                <xsl:if test="$callback-params">
                    <xsl:copy-of select="$callback-params"/>
                </xsl:if>
            </xsl:element>
        </xsl:variable>

        <xsl:apply-templates select="exsl:node-set($callback-node)" mode="iterator-callback">
            <xsl:with-param name="position" select="$position"/>
        </xsl:apply-templates>

        <xsl:call-template name="iterator">
            <xsl:with-param name="start" select="$start"/>
            <xsl:with-param name="iterations" select="$iterations"/>
            <xsl:with-param name="direction" select="$direction"/>
            <xsl:with-param name="callback" select="$callback"/>
            <xsl:with-param name="callback-params" select="$callback-params"/>
            <xsl:with-param name="count" select="$count - 1"/>
        </xsl:call-template>

    </xsl:if> 

</xsl:template>

Additional parameters can be passed for more advanced iterations and callbacks:

start allows you to start the iteration from a specific number, defaults to 1:

<xsl:with-param name="start" select="'3'"/>

iterations is the number of iterations to perform:

<xsl:with-param name="iterations" select="'100'"/>

direction allows you to count down (“-“) rather than the default up (“+”)

<xsl:with-param name="direction" select="'-'"/>

callback is the name of the XML node created to match on with your callback template

<xsl:with-param name="callback" select="'my-template'"/>

callback-params accepts XML which are then passed to the callback template

<xsl:with-param name="callback-params">
    <name>Nick Dunn</name>
</xsl:with-param>

<xsl:template match="render-user" mode="iterator-callback">
    <xsl:param name="position"/>
    <p>Name: <xsl:value-of select="name"/></p>
</xsl:template>

(Note: you will need to include the EXSLT common namespace in your stylesheet to use the node-set function in the template above!)

Conclusion

We have seen the different ways of achieving a numeric for loop in XSLT, and in doing so created a re-usable recursive template with a dynamic callback. I’ve not seen this callback method documented anywhere else, so this may be a new technique that has novel applications beyond this example. Recurse to the max, don’t tokenize.

Orchestrated by Symphony CMS