Manipulate XSLTsearch

When developing websites with Umbraco, I always use the XSLTsearch package to handle the search solution. As well as being easy and quick to install, it is customisable and very fast in searching content nodes.

As much as I love XSLTsearch, the one dilemma I always face is having to modify the HTML output that is generated.  Given the way I work; with a much better front-end developer providing the mark-up; I am faced with shoehorning my HTML into the XSLTsearch template.

In many cases this is fine and acceptable. However how to handle bugfixes and overall improvements to XSLTsearch when they may be released? Having to retro-fit these into my forked/modified/hacked version is an unwanted headache. (Also having learnt from past experiences in open-source development, you do not hack the core!)

So how can we separate our desired mark-up from the logic/core of XSLTsearch? (without modifying XSLTsearch itself!)


Now we all know that the beauty of XSLT is in its ability to transform one flavour of XML into another flavour of XML; whether this be XHTML, RSS, etc. The XML is processed and returned. With this in mind, we can alter our perception of the output from XSLTsearch as a data-source, rather than HTML output.

Reviewing the XSLTsearch source, skipping over all the variable declarations, the root template runs a couple of conditions on the $search and $source parameters, then ultimately calls a template named “search” – passing through a parameter called “items” containing an XPath for the selected node-set.

Using a separate XSLT file, we can import “XSLTsearch.xslt” and override its templates with our own – this is done by using the “priority” attribute on our xsl:template. From here we can make our own call to the “search” template and pass through any XPath we desire in the “items” parameter.

To do this…

  1. Create a new XSLT file called “SearchResults.xslt” – you can do this either from your Umbraco back-office or on directly on the file-system (in the /xslt directory).
  2. Find the macro for XSLTsearch, (via the Umbraco back-office), change the “Use XSLT file” to “SearchResults.xslt” (e.g. the one you’ve just created).
  3. Copy-n-paste the following snippet, (or get the full XSLT from my gist):
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xsl:stylesheet [
	<!ENTITY nbsp "&#x00A0;">
]>
<xsl:stylesheet
	version="1.0"
	xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
	xmlns:msxml="urn:schemas-microsoft-com:xslt"
	xmlns:umbraco.library="urn:umbraco.library"
	xmlns:PS.XSLTsearch="urn:PS.XSLTsearch"
	exclude-result-prefixes="msxml umbraco.library PS.XSLTsearch">
	<xsl:import href="XSLTsearch.xslt"/>

	<xsl:template match="/" priority="2">
		<xsl:variable name="searchResults">
			<xsl:call-template name="search">
				<xsl:with-param name="items" select="$currentPage/ancestor-or-self::*[@level = 1]"/>
			</xsl:call-template>
		</xsl:variable>
		<xsl:variable name="results" select="msxml:node-set($searchResults)"/>

		<xmp>
			<xsl:copy-of select="$results"/>
		</xmp>

	</xsl:template>

</xsl:stylesheet>

This is a snippet for my blog post, to get my full customised XSLT example, see here: https://gist.github.com/1879072

So, what has just happened?

We’ve included an import reference for the unmodified XSLTsearch file. Our root template (match=”/”) is given a priority of 2; this tells the XSLT processor that our template takes a higher priority that XSLTsearch’s original template.

Inside our template we declare a variable named “searchResults” (you can call this whatever you like), the value of this will be the output from XSLTsearch’s template named “search”, passing in the “items” parameter.

It is important to point out that the value of the “searchResults” variable will be a result tree fragment, meaning we can’t use it as we would a regular XML node-set. This usually causes headaches for developers – it’s generally at the point when they want to throw their laptop out of the window and pledge allegiance to the Razor Empire. So to resolve this, we need the follow-up variable called “result” – this uses a native extension method to convert the fragment back into a proper node-set.

Once we have our “$results” variable, we can manipulate this however we like.  On a side note, do read the Pimp My XSLT article on “Transforming WYSIWYG output with XSLT“.

My use of the <xmp> tag is for debug purposes only … yes, yes, I know it has been deprecated since HTML 3.2, but as long as browsers support it, I’ll use it … and no, I’ve never ever used it on a production website.

From here you can do an xsl:apply-templates on the $result node-set and manipulate the search results however you desire.

<xsl:apply-templates select="$results/div" />

Another advantage of taking this approach is to be able to manipulate the XPath expression of the “items” parameter.

Let’s say that you only wanted to search against your news articles; we could modify the XPath expression to something like this…

<xsl:with-param name="items" select="$currentPage/ancestor-or-self::*[@level = 1]/descendant::NewsArticle[@isDoc]"/>

This XPath navigates all the way up the tree to the homepage node (level 1), then back down collecting all the ‘NewsArticle’ nodes.

Or how’s about  something more advanced? We would like only news articles published in the last 30 days.

<xsl:with-param name="items" select="$currentPage/ancestor-or-self::*[@level = 1]/descendant::NewsArticle[@isDoc and umbraco.library:DateGreaterThanOrEqualToday(umbraco.library:DateAdd(@createDate, 'd', 30))]"/>

In summary, once you are able to change your perspective that the output from an XSLT is still XML, which you can manipulate and transform further – you have complete control over your desired mark-up.

Robots.txt Editor for Umbraco 5

First migration of my Umbraco packages to the newly released v5 (Jupiter), I am proud to announce… Robots.txt Editor for Umbraco 5!

The majority of the re-development was done during the #umbWeekend (last weekend – 27th January). It was fun to explore the new codebase and APIs for Umbraco v5; creating tree nodes and building the editor.  Then a few evenings this week to polish-up the UI, etc.

For any developers wanting to know more about the code/structure, please do take a look at the source code.  Any questions, catch me on Twitter.

Want to help develop Google Maps Umbraco package?

There are 2 outstanding bugs in the Google Maps for Umbraco package. Would you like to help us fix these bugs and collaborate on the project?

My current workload is high and I am aware that there are 2 major bugs that need fixing on the Google Map data-type. With my heavy involvement on the uComponents project, it’s unlikely I will fix these bugs any time soon, hence the ‘call for help’.

If you have been wanting to get more involved with the Umbraco community and earn some karma, this is an ideal way to get involved.

The Google Maps data-type source-code is available on my BitBucket repository, feel free to make a fork and submit any pull requests!

Update: Sam Moore came to the rescue and squished the 2 bugs! #h5yr Sam!

uComponents: 100 karma votes and 10,000 downloads!

Very proud and happy to announce that uComponents has reached 100 karma votes and 10,000 downloads! (that’s not including the additional 4,000 download from our CodePlex project)

A huge thank you to the uComponents team for developing a great set of Umbraco components – and an even bigger THANK YOU to the Umbraco community for use it! #h5yr

WordPress 3 Plugin Development Essentials

wordpress-3-plugin-development-essentials It has been a while since I last developed a plugin for WordPress. With the release of version 3, I have been eager to learn about new improvements with plugin development. Having recently got hold of a copy of WordPress 3 Plugin Development Essentials (Packt Publishing, 2011), I’ve shaken the dust off my WordPress skills!

Whether you are a newcomer to WordPress, as long as you have some basic PHP knowledge, WordPress 3 Plugin Development Essentials provides a good solid foundation for how to develop your own plugins for WordPress. The book provides practical hands-on tutorials, best coding guidelines and good architecture advice for developing original plugins.

The first two chapters are aimed to ease you into preparing for WordPress, understanding the framework, setting up a development environment and an anatomy of a plugin.
Next few chapters are examples of specific plugin functionality. With the remaining several chapters focusing on the deployment, distribution and maintenance of your plugins.

If you are looking to get into plugin development, I’d recommend picking up a copy of WordPress 3 Plugin Development Essentials – while it is not intended to teach you PHP or MySQL, there focus is more on the core concepts, so even regular users of WordPress can delve into making their own basic plugins.

Having previous read (and reviewed) WordPress Plugin Development: Beginner’s Guide, (Vladimir Prelovac, Packt Publishing, 2009), there are many similarities between both books. I’d say that WordPress 3 Plugin Development Essentials offers a broader scope and range of topics.

In particular I was impressed with the level of detail on how to use Subversion (Chapter 8) , especially with how to overcome various errors and reverting to previous versions.

Standardized Custom Content (Chapter 6) is also a good resource if you are interested in pushing the boundaries of WordPress towards being a custom content management system.

Having had a fair amount of experience with developing WordPress plugin in the past, I was already familiar with most of the concepts – this book helped to reinforce those principles. If you are interested in learning more how to develop your own WordPress plugins, I would recommend that you pick up a copy of this book.

Discounts on WordPress books during June at Packt

Packt Publishing are having a special discount on their range of WordPress books during June. If you are doing WordPress development or are interested in starting out, then take a look at their selection.

They’ve just released “WordPress 3 Ultimate Security“, which should be essential reading for anyone wanting to protect their hosted WordPress installs!

To see the discounts, go to Packt’s WordPress Month page.

Running Umbraco from a USB drive

With the release of Umbraco 4.6 (Juno), users now have the option of using Microsoft’s new embedded database engine, SQL CE 4. This means that you don’t need to depend on using a database server (such as SQL Server [Express] or MySQL), you can run Umbraco exclusively from the file-system!

Also recently released is IIS Express 7.5, (another Microsoft web technology, as part of their WebMatrix framework), which offers a lightweight version of IIS – aimed at developers as a replacement for the Cassini web-server.  One of the major features of IIS Express are that it can be launched straight from disk – it does not need to be registered/configured on the operating-system/machine.

Now, this got me thinking… Would it be possible to run Umbraco from a USB drive? Well, guess what?

Best of all its very very easy to do… here’s how:

  • Download and install IIS Express 7.5 and SQL CE 4 – the quickest and easiest way is to install WebMatrix.
  • Download Umbraco 4.6.1 (latest version at the time of writing) and also the “SQLCE4Umbraco.dll” assembly.
  • Copy the following to your USB drive:
    • Extract the Umbraco zip file, rename the “build” folder to something else – like “wwwroot”, then copy that to the USB.
    • Copy over the “SQLCE4Umbraco.dll” into the “wwwrootbin” directory.
    • Copy the “IIS Express” directory (typically found at “C:Program Files (x86)IIS Express”) to the USB.
    • Copy the SQL CE 4 binaries (typically found at “C:Program Files (x86)Microsoft SQL Server Compact Editionv4.0Private”) - also copy the “amd64″ and “x86″ sub-directories - to the “wwwrootbin” on the USB drive.
  • Once everything is in place, you should have 2 root directories, “IIS Express” and “wwwroot”.
  • Open up a command prompt, run the following command:
"E:IIS Expressiisexpress.exe" /path:E:wwwroot /port:8080
  • Open a new web-browser window, go to “http://localhost:8080″.
  • If everything went to plan, the command prompt will display an output of all incoming requests.
  • Back in the web-browser window, you should be prompted with the Umbraco installer wizard.  If not, something went wrong! :-(
  • Remember to used the SQL CE 4 database engine!!! (otherwise it wont be portable)

Once I had successfully installed Umbraco, I tried out a few packages; e.g. uComponents, set up an MNTP data-type, which worked as expected! Great!

After that I removed the USB drive; booted up my old laptop (Windows XP SP3) to see if it would still work.  First try it failed! I didn’t have .NET 4.0 framework installed.  Once I installed it, re-ran the command prompt – portable Umbraco worked as expected!

One point to raise is that I did notice slower performance of the Umbraco back-office – which doesn’t surprise me – since I was using a fairly old USB drive, but still the lag wasn’t enough to be overly concerned about.

Personally I see the portability of Umbraco to be very useful for client/customer demos/meetings… for any Umbraco developers who want to showcase their favourite CMS, now there is no excuse not to have a working copy in your pocket!

How to use umbraco.library GetMedia in XSLT for Umbraco v4.5

This is a quick follow-up on my previous blog post: “How to use umbraco.library GetMedia in XSLT“.  At the request of fellow Umbraco South-West UK developer, Dan, that I should update the code snippets for the new XML schema in Umbraco v4.5+

First a quick notice; if you are using v4.5.0, then please upgrade to v4.5.1, as there was a tiny bug in GetMedia that caused great confusion and headaches – you have been advised!

Without further ado, the updated XSLT snippet that you came here for…

<xsl:template match="/">
	<xsl:variable name="mediaId" select="number($currentPage/mediaId)" />
	<xsl:if test="$mediaId > 0">
		<xsl:variable name="mediaNode" select="umbraco.library:GetMedia($mediaId, 0)" />
		<xsl:if test="$mediaNode/umbracoFile">
			<img src="{$mediaNode/umbracoFile}" alt="[image]" height="{umbracoHeight}" width="{umbracoWidth}" />
		</xsl:if>
	</xsl:if>
</xsl:template>

Any questions? Come join us over at Our Umbraco… we are a friendly bunch!

ASP.NET System Information for Umbraco

Released a new Umbraco package today, that integrates the ASP.NET System Information Prober into the Umbraco back-office.

What is the ASP.NET System Information Prober? It is a single page that tries to get as much useful hosting information about your web-server. The concept is similar to PHP’s native phpinfo() function.

Installing the package will add a new node tree to the developer section.

Here is a quick demo video: http://screenr.com/2YC

Installing this package will add a new node tree to the developer section.

You can download the ASP.NET System Information for Umbraco package from the Our Umbraco community site.

Working with XSLT using new XML schema in Umbraco 4.1

Most of the Umbraco community are aware that the XML schema in the upcoming Umbraco 4.1 release has changed.

Instead of each document being a node element, the element name is the node-type alias, same with property values; they no longer use data elements with alias attributes. Here is a quick example, comparing the old/legacy with the new:

<node id="1066" parentID="-1" level="1" nodeName="Home" ... nodeTypeAlias="Homepage" path="-1,1066">
	<data alias="bodyText"><![CDATA[<p>Welcome to my homepage.</p>]]></data>
</node>
<Homepage id="1066" parentID="-1" level="1" ... nodeName="Home" path="-1,1066" isDoc="">
    <bodyText><![CDATA[<p>Welcome to my homepage.</p>]]></bodyText>
</Homepage>

Obviously for long-time Umbraco developers this will require a small shift in mindset, as we are way too familiar with writing XPath queries like;

$currentPage/descendant-or-self::node[string(data[@alias='umbracoNaviHide'])  != '1']

… which will need to be rewritten to;

$currentPage/descendant-or-self::*[umbracoNaviHide != '1']

Not that it’s a difficult thing to change/update, but I can see a lot of questions being asked on the Our Umbraco forum.

Since there are a lot of existing Umbraco packages that use the current, (soon to be legacy) XML schema, it might be worthwhile making use of XSLT itself to convert the new back to the old – in order to keep the existing XSLT templates working.  Here’s a quick example:

<!-- ROOT element -->
<xsl:template match="root">
	<xsl:element name="root">
		<xsl:apply-templates select="child::*" />
	</xsl:element>
</xsl:template>

<!-- NODE elements -->
<xsl:template match="*[count(@isDoc) = 1]">
	<xsl:element name="node">
		<xsl:attribute name="nodeTypeAlias">
			<xsl:value-of select="local-name()"/>
		</xsl:attribute>
		<xsl:copy-of select="@*" />
		<xsl:apply-templates select="child::*" />
	</xsl:element>
</xsl:template>

<!-- DATA elements -->
<xsl:template match="*[count(parent::*) &gt; 0 and count(@isDoc) = 0]">
	<xsl:element name="data">
		<xsl:attribute name="alias">
			<xsl:value-of select="local-name()"/>
		</xsl:attribute>
		<xsl:copy-of select="text()" />
	</xsl:element>
</xsl:template>

These templates would be used to transform the new schema/structure back to the old legacy schema/structure, like so:

<xsl:variable name="legacyFragment">
	<xsl:apply-templates select="$currentPage/ancestor::root" />
</xsl:variable>
<xsl:variable name="legacyRoot" select="msxml:node-set($legacyFragment)/root" />
<xsl:variable name="legacyCurrentPage" select="$legacyRoot/descendant-or-self::node[@id = $currentPage/@id]" />

Since you can’t modify a variable’s value in XSLT, it would be a case of replacing all the “$currentPage” references with “$legacyCurrentPage” (or whatever you decided to call it). But in all honesty, if you are going to start modifying your XSLT, then it would be better to refactor the XPath statements to use the new schema!

Personally, I’m looking forward to using the new XML schema in Umbraco 4.1, the structure makes more sense from a semantic perspective – and I am told it will have performance gains on the XSLT processor.

Updated Robots.txt Editor for Umbraco

Last night I released version 2 of the Robots.txt Editor for Umbraco.

Changes & new features:

  • Restructured the package files, they all live in a folder called “robots-txt” (still under the /umbraco folder – but self-contained)
  • Errors are now displayed using the Feedback control (as opposed to the Speech Bubble in the bottom-right corner).
  • Robots.txt editor has buttons for adding new User-Agent and Disallow rules, as well as comment/uncomment functionality.
  • Changed the Robot icon… courtesy of Mozilla Firefox’s “about:robots” favicon.

Hope you all enjoy the update… if you come across any bugs or ideas for a future release, please let me know via the our.umbraco forum.

How to use umbraco.library GetMedia in XSLT

From time to time I notice a reoccurring post over at the Our Umbraco forum; how to display an image (from the Media section) in XSLT?

A quick answer can be found on the Our Umbraco wiki for the umbraco.library GetMedia method.

For most uses, the last example in the wiki works great.  But I want to show you a “super safe” way of dealing with GetMedia in XSLT.

Where I find a lot of the examples go wrong is that they make the assumption that a media node (XML) is returned from the GetMedia call, e.g.

<xsl:value-of select="umbraco.library:GetMedia($currentPage/data[@alias='mediaId'], 'false')/data[@alias='umbracoFile']" />

If the ‘mediaId’ property didn’t contain either a numeric value or a valid media node id, then it would return null … meaning that the following “/data” would throw an Exception! (Displaying “Error parsing XSLT file” message on the front-end.)  Not what you or your users want to see!

In order to consider any user inputs, like media IDs not being selected, or even a referenced media node is deleted in the back-office, here is the “super safe” approach:

<xsl:template match="/">
	<xsl:variable name="mediaId" select="number($currentPage/data[@alias='mediaId'])" />
	<xsl:if test="$mediaId &gt; 0">
		<xsl:variable name="mediaNode" select="umbraco.library:GetMedia($mediaId, 0)" />
		<xsl:if test="count($mediaNode/data) &gt; 0">
			<xsl:if test="string($mediaNode/data[@alias='umbracoFile']) != ''">
				<img src="{$mediaNode/data[@alias='umbracoFile']}" alt="[image]">
					<xsl:if test="string($mediaNode/data[@alias='umbracoHeight']) != ''">
						<xsl:attribute name="height">
							<xsl:value-of select="$mediaNode/data[@alias='umbracoHeight']" />
						</xsl:attribute>
					</xsl:if>
					<xsl:if test="string($mediaNode/data[@alias='umbracoWidth']) != ''">
						<xsl:attribute name="width">
							<xsl:value-of select="$mediaNode/data[@alias='umbracoWidth']" />
						</xsl:attribute>
					</xsl:if>
				</img>
			</xsl:if>
		</xsl:if>
	</xsl:if>
</xsl:template>

Here’s what happens:

  1. The “mediaId” is pulled from a property of the “currentPage” and cast as a number.  Optionally the “mediaId” could be passed in via a macro parameter, or somewhere else?
  2. The first condition checks the the “mediaId” is numeric, and greater-than zero.
  3. The “mediaId” is passed through to “GetMedia”, along with the false flag to only pull-back the required node (not it’s children, for Folder media items).
  4. We check if the media node has any child “data” elements – which contain the data about the image/media.
  5. Then we check if the “umbracoFile” property has any data – if not, then there is no point displaying an image.
  6. There are extra conditions for the “height” and “width” properties – these are optional.

Personally, I add an “altText” property to the Image media-type … and use that in the XSLT – again this is optional, but strongly recommended!

I can see how this “super safe” approach is overkill – especially compared with a single line of XSLT … but from my experience, it’s better to be safe than sorry – especially when dealing with user data-input – your assumptions and expectations of how users will use the system aren’t always correct!

Update: OK, I agree the extra “if” statements are overkill… so here’s a condensed version – assuming that the “umbracoHeight” and “umbracoWidth” properties are always there…

<xsl:template match="/">
	<xsl:variable name="mediaId" select="number($currentPage/data[@alias='mediaId'])" />
	<xsl:if test="$mediaId &gt; 0">
		<xsl:variable name="mediaNode" select="umbraco.library:GetMedia($mediaId, 0)" />
		<xsl:if test="count($mediaNode/data) &gt; 0 and string($mediaNode/data[@alias='umbracoFile']) != ''">
			<img src="{$mediaNode/data[@alias='umbracoFile']}" alt="[image]" height="{$mediaNode/data[@alias='umbracoHeight']}" width="{$mediaNode/data[@alias='umbracoWidth']}" />
		</xsl:if>
	</xsl:if>
</xsl:template> 

WordPress Plugin Development: Beginner’s Guide, by Vladimir Prelovac

wordpress-plugin-development-book I have recently finished reading Vladimir Prelovac book on WordPress plug-in development, (WordPress Plug-in Development: Beginner’s Guide, Packt Publishing, 2009).

As an experienced WordPress plug-in developer, I was pessimistic at the start – there is already a wealth of documentation and detailed tutorials on the web, who would need a book? However with Vladimir being a well-respected WordPress plug-in developer, I was curious to see his approach on the subject, and you never know – I may learn a thing or two? (hint: I did!)

WordPress Plug-in Development (Beginner’s Guide) is a great introduction to the WordPress platform, the plug-in architecture and the ever-growing community surrounding it.

The first thing I noticed was that the book is centred around WordPress 2.6, (at the time of writing the latest version is 2.8.4, with 2.9 due out very soon), unfortunately all of the screenshots for the admin back-end are outdated, since there was a complete overhaul to the design in version 2.7. This is no fault of the author, but an example of how fast paced the WordPress developer community is. Luckily, the principles that Vladimir explains are focused on the core WordPress functionality, which are solid and stable.

Throughout the book, Vladimir encourages you to “hack” around with code, which for me is a great experience – it’s how I learnt to code! As the tagline of the book states: “Learn by doing: less theory, more results“.

There is also a great awareness of 3rd-party applications, libraries and resources, (like Digg, jQuery, Poedit, etc), which is fine for experienced web-developers, but for beginners – it will open up a world of exciting developments! Thinking back to when I first played with jQuery… or pulling my photos back from Flickr’s API… so cool!

The very nice people at Packt Publishing have a sample chapter available on-line; Chapter 2: Social Bookmarking, covers how to develop your own Digg button for your blog.

Vladimir covers all areas of WordPress development, from action and filter hooks to shortcodes and widgets to localisation (i18n & L10n). Even I didn’t know about the “wp_localize_script” function!

The mantra of the book is to leverage WordPress whenever you can, try not to re-invent the wheel. Which reminds me of Peteris Krumins‘ blog quote: “good coders code, great reuse”!

As the book progresses, each chapter’s example plug-in becomes more challenging and complex. The focus on localisation over the last few chapters was most interesting for me, as it is (probably) the least understood concept in WordPress plug-in development!

Often it is easy for WordPress users to take plug-in functionality for granted, this book exposes the amount of thought, planning, design and skill that goes into every (popular) WordPress plug-in.

In summary, WordPress Plug-in Development (Beginner’s Guide) is perfect for anyone who is interested in extending the functionality of WordPress – it goes without saying that a little PHP knowledge is required, but that isn’t a show-stopper, you can learn whilst you “hack”!