<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rssdatehelper="urn:rssdatehelper"><channel><title>Percipient Blog</title><copyright>Copyright 2009, Percipient Studios. All rights reserved.</copyright><link>http://blog.percipientstudios.com</link><pubDate></pubDate><generator>umbraco</generator><description></description><image><url>http://blog.percipientstudios.com/images/logo-brand-blog-55.png</url><title>Percipient Blog</title><link>http://blog.percipientstudios.com</link></image><language>en</language><item><title>XSLTsearch supports Umbraco 4.1</title><link>http://blog.percipientstudios.com/2010/6/15/xsltsearch-supports-umbraco-41.aspx</link><pubDate>Tue, 15 Jun 2010 12:01:54 GMT</pubDate><guid>http://blog.percipientstudios.com/2010/6/15/xsltsearch-supports-umbraco-41.aspx</guid><description>
&lt;p&gt;Coinciding with the release of Umbraco 4.1RC, we have updated
XSLTsearch to work perfectly with the new xml schema. Download
XSLTsearch 2.8.1 today!&lt;/p&gt;
</description><author>info@percipientstudios.com (Douglas Robar)</author><content:encoded><![CDATA[ <p>Coinciding with the release of <a href="http://umbraco.org/blog/2010/6/15/umbraco-41rc-is-out">Umbraco 4.1RC</a>, we have updated <a href="http://www.percipientstudios.com/xsltsearch.aspx">XSLTsearch</a> to work perfectly with the new xml schema.</p>
<p><strong>XSLTsearch 2.8.1 is now available for download at<br /><a href="http://our.umbraco.org/projects/xsltsearch">http://our.umbraco.org/projects/xsltsearch</a></strong></p>
<p>Please continue to use XSLTsearch 2.8 for Umbraco 3.x, 4.0, and 4.1 sites with the legacy xml schema enabled.</p>
<p>&nbsp;</p>
<p>cheers,<br />doug.</p>]]></content:encoded></item><item><title>The never-expiring copyright date</title><link>http://blog.percipientstudios.com/2010/1/2/the-never-expiring-copyright-date.aspx</link><pubDate>Sat, 02 Jan 2010 18:28:19 GMT</pubDate><guid>http://blog.percipientstudios.com/2010/1/2/the-never-expiring-copyright-date.aspx</guid><description>
&lt;p&gt;It's January 2... do you know if your site's copyright notice is
up-to-date?&lt;/p&gt;

&lt;p&gt;With a quick bit of inline XSLT in your umbraco template you
need never worry about it again!&lt;/p&gt;
</description><author>info@percipientstudios.com (Douglas Robar)</author><content:encoded><![CDATA[ <p>It's January 2... do you know if your site's copyright notice is up-to-date?</p>

<p>With a quick bit of <a href="http://our.umbraco.org/wiki/reference/templates/umbracoitem-element/inline-xslt/how-to-use-it" target="_blank">inline XSLT</a> in your umbraco template you need never worry about it again!</p>
<p>Here's how to do it:</p>

<pre class="brush: xml;">
&lt;div id="footer"&gt;
    COPYRIGHT &amp;copy; 2009 - 
    &lt;umbraco:Item field="pageName" runat="server" xslt="Exslt.ExsltDatesAndTimes:year()" /&gt;, 
    PERCIPIENT STUDIOS. ALL RIGHTS RESERVED.
&lt;/div&gt;
</pre>

<p>There are three points you'll want to keep in mind:
<ul>
<li>You must not omit the field="" parameter.</li>
<li>You must select a field="" that actually exists.<br />This is why I used the "pageName" field.</li>
<li>You can select any field="" you want.<br />Remember that the xslt="" command will process the field="" parameter passed in before displaying the output; and in our example the xslt ignores the field being passed in.</li>
</ul>
</p>

<h2>Alternatives</h2>
<p>Or, if you have some objection to the Exslt extension and want to use only the umbraco library, you can achieve the same result with:
</p>
<pre class="brush: xml;">
    &lt;umbraco:Item field="pageName" runat="server" xslt="umbraco.library:FormatDateTime(umbraco.library:CurrentDate(), 'yyyy')" /&gt;,
</pre>

<p>Or, if you really want to use a full macro, it would look like this:</p>
<pre class="brush: xml;">
&lt;xsl:template match="/"&gt;
    &lt;xsl:value-of select="Exslt.ExsltDatesAndTimes:year()" /&gt;
&lt;/xsl:template&gt;
</pre>

<p>[EDIT] Or, as Casey points out in the comments... if you have a deep love for all things .NET (or aren't a fan of XSLT) you could put this in your template instead of the umbraco:Item:</p>
<pre class="brush: csharp;">
    &lt;%= DateTime.Now.Year %&gt;
</pre>

<h2>Conclusion</h2>
<p>You can now sleep through New Year's day comfortably, thanks to umbraco and XSLT.</p>
<p>Happy New Year!<br />doug.</p>]]></content:encoded></item><item><title>Advanced XSLT with .NET Namespaces</title><link>http://blog.percipientstudios.com/2009/9/21/advanced-xslt-with-net-namespaces.aspx</link><pubDate>Mon, 21 Sep 2009 12:54:33 GMT</pubDate><guid>http://blog.percipientstudios.com/2009/9/21/advanced-xslt-with-net-namespaces.aspx</guid><description>
&lt;p&gt;Extending your umbraco XSLT macros to access .NET namespaces is
very simple and will help you make the most of your macros. An
example of file-level access from an XSLT macro is provided.&lt;/p&gt;
</description><author>info@percipientstudios.com (Douglas Robar)</author><content:encoded><![CDATA[ <p>I prefer to use XSLT macros whenever possible, resorting to C#
only when I absolutely have to.</p>

<p>Until recently I have created .net macros for even simple
functionality that I would have preferred to put in an
easily-maintained XSLT macro. Why? Because I couldn't access a
needed namespace from within XSLT.</p>

<h2>An example: file level operations</h2>

<p>A recent site I worked on needed to display the size of a file.
If the file were in umbraco's Media section this would be easy with
the built-in <strong>umbracoBytes</strong> property. But in this
case, the file was uploaded rather than placed in umbraco's Media
section. Thus, the usual umbraco metadata was not available.</p>

<p>Various solutions presented themselves:</p>

<ul>
<li>Add an <strong>'umbracoBytes' property</strong> (of type label
or static text) to my document type. Umbraco will auto-populate this
property when a file is uploaded (this is VERY cool and a great tip
to remember!). In my case, however, I had four upload fields in
the docType and whatever file was uploaded last would have its
filesize placed in the 'umbracoBytes' field. I needed a solution
that would work for all the files uploaded.</li>

<li>Create an <strong>event handler</strong> setting a unique
uploadFile1_umbracoBytes, uploadFile2_umbracoBytes, etc. property
when uploading the file. This seemed like too much effort and I
would be sure to forget to update the event handler should a fifth
upload field be added to the docType later on.</li>

<li>Create a <strong>custom XSLT extension</strong> to get the
filesize information. This is a good solution but a whole extension
seemed rather over-kill for a few lines of C# code.</li>
</ul>

<p>The C# function I wanted to use was very simple, taking the path
to a file and returning the filesize in kilobytes. This could
certainly be done as an XSLT extension:</p>

<pre class="brush: csharp; gutter: false;">
public String uploadFileSize(String filePath) {

    if ((filePath != null) &amp;&amp; (filePath.Length != 0)) {
        String localFile = HttpContext.Current.Server.MapPath(filePath);
        if (File.Exists(localFile)) {
            FileInfo fileinfo = new FileInfo(localFile);
            return String.Format("{0:#,###,###.##}", (fileinfo.Length / 1024));
        }
    }
    return null;
}
</pre>

<h2>Using .NET namespaces in your XSLT macros</h2>

<p>What I really wanted to do was augment my XSLT macro with that
bit of C# code to get the file size from within the XSLT file
itself, without needing to create a .NET control, some app_code, an
event handler, or custom XSLT extension.</p>

<p>Unfortunately, file level access and many other fun capabilities
are not allowed in your umbraco XSLT macros. Not by default, that
is. But it's really simple to add that ability with in-line C# (a
topic we'll cover in another post) in your XSLT macro.</p>

<pre class="brush: csharp; gutter: false;">
&lt;msxml:script language="CSharp" implements-prefix="ps"&gt;
    &lt;msxml:using namespace="System.IO" /&gt;
    &lt;msxml:assembly name="System.Web" /&gt;
    &lt;msxml:using namespace="System.Web" /&gt;

    &lt;![CDATA[
    public String uploadFileSize(String filePath) {

        if ((filePath != null) &amp;&amp; (filePath.Length != 0)) {
            String localFile = HttpContext.Current.Server.MapPath(filePath);
            if (File.Exists(localFile)) {
                FileInfo fileinfo = new FileInfo(localFile);
                return String.Format("{0:#,###,###.##}", (fileinfo.Length / 1024));
            }
        }
        return null;
    }
    ]]&gt;
&lt;/msxml:script&gt;
</pre>

<p><br />
The <strong>msxml:using</strong> and
<strong>msxml:assembly</strong> statements are the important bits. The msxml:assembly loads the assembly like adding a reference in a .NET project. The msxml:using makes using the functions shorter with no prefix required, just as <strong>using
System.IO;</strong> and <strong>using System.Web;</strong> in your
C# code would do.</p>
<p>I found System.IO was already available so I didn't need to add the assembly statement for it. System.Web was not available so I added it with the msxml:assembly statement.</p>

<h2>Completed XSLT macro with in-line .NET code</h2>

<p>Here is a complete (and very simple, rather hard-coded) XSLT
file. Your macros would probably have more logic in the main
template, possibly set the uploadedFile variable with a macro
parameter (using a propertyPicker data type), and include
additional checks for errors.&nbsp;</p>

<pre class="brush: csharp; gutter: false;">
&lt;!DOCTYPE xsl:stylesheet [
    &lt;!ENTITY nbsp "&amp;#x00A0;"&gt;
]&gt;
&lt;xsl:stylesheet
    version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxml="urn:schemas-microsoft-com:xslt"
    xmlns:ps="urn:schemas-percipient-studios"
    xmlns:umbraco.library="urn:umbraco.library"
    exclude-result-prefixes="msxml ps umbraco.library" &gt;

    &lt;xsl:output method="xml" omit-xml-declaration="yes" /&gt;

    &lt;xsl:param name="currentPage"/&gt;

    &lt;!-- =========================================================== --&gt;

    &lt;xsl:template match="/"&gt;
        &lt;xsl:variable name="uploadedFile" select="$currentPage/data[@alias='uploadedFile']" /&gt;
        &lt;xsl:if test="string($uploadedFile) != ''"&gt;
            &lt;p&gt;
                The size of the uploaded file is:
                &lt;xsl:value-of select="ps:uploadFileSize($uploadedFile)" /&gt; kb
            &lt;/p&gt;
        &lt;/xsl:if&gt;
    &lt;/xsl:template&gt;

    &lt;!-- =========================================================== --&gt;

    &lt;msxml:script language="CSharp" implements-prefix="ps"&gt;
        &lt;msxml:using namespace="System.IO" /&gt;
        &lt;msxml:assembly name="System.Web" /&gt;
        &lt;msxml:using namespace="System.Web" /&gt;

        &lt;![CDATA[
        public String uploadFileSize(String filePath) {

            if ((filePath != null) &amp;&amp; (filePath.Length != 0)) {
                String localFile = HttpContext.Current.Server.MapPath(filePath);
                if (File.Exists(localFile)) {
                    FileInfo fileinfo = new FileInfo(localFile);
                    return String.Format("{0:#,###,###.##}", (fileinfo.Length / 1024));
                }
            }
            return null;
        }
        ]]&gt;
    &lt;/msxml:script&gt;

    &lt;!-- =========================================================== --&gt;
                
&lt;/xsl:stylesheet&gt;
</pre>

<h2>Conclusion</h2>

<p>As you can see, extending your XSLT macros with a bit of .NET
functionality is very simple and will help you make the most of
your macros. And because XSLT macros are compiled, performance is
not a problem, though I also cached this macro heavily as well just to be on the safe side.</p>
]]></content:encoded></item><item><title>What I wish I had known in my first 30 days with umbraco</title><link>http://blog.percipientstudios.com/2009/6/22/what-i-wish-i-had-known-in-my-first-30-days-with-umbraco.aspx</link><pubDate>Mon, 22 Jun 2009 17:37:49 GMT</pubDate><guid>http://blog.percipientstudios.com/2009/6/22/what-i-wish-i-had-known-in-my-first-30-days-with-umbraco.aspx</guid><description>
&lt;p&gt;Download my slides from Umbraco CodeGarden '09 presentation,
&quot;What I wish I had known in my first 30 days with umbraco&quot;
(PDF).&lt;/p&gt;

&lt;p&gt;A fast-paced session for beginners who want to learn from
(rather than repeat) others' mistakes, focusing on concepts, best
practices, tips, hidden gems, and &quot;rules of thumb&quot;&lt;/p&gt;
</description><author>info@percipientstudios.com (Douglas Robar)</author><content:encoded><![CDATA[ <p>Download my slides from Umbraco CodeGarden '09 and the 2009 umbracoUK meetup entitled, <a href="http://blog.percipientstudios.com/media/971/what%20i%20wish%20i%20had%20known.pdf"><strong>What I wish I had known in my first 30 days with umbraco</strong></a> (PDF).</p>
<p>A fast-paced session for beginners who want to learn from (rather than repeat) others’ mistakes, focusing on concepts, best practices, tips, hidden gems, and "rules of thumb"</p>]]></content:encoded></item><item><title>Your first umbraco XSLT macro</title><link>http://blog.percipientstudios.com/2009/5/5/your-first-umbraco-xslt-macro.aspx</link><pubDate>Tue, 05 May 2009 18:30:03 GMT</pubDate><guid>http://blog.percipientstudios.com/2009/5/5/your-first-umbraco-xslt-macro.aspx</guid><description>
&lt;p&gt;Create your first XSLT macro in umbraco and greet the world!&lt;/p&gt;

&lt;p&gt;In this article you'll learn the steps to create an XSLT macro
and insert that macro into a template. You'll also learn that what
you type in XSLT is what you get out of XSLT for both text and HTML
tags.&lt;/p&gt;

&lt;p&gt;This article is foundational to working with umbraco XSLT-based
macros and you won't want to miss it.&lt;/p&gt;
</description><author>info@percipientstudios.com (Douglas Robar)</author><content:encoded><![CDATA[ <p>The first program you write when learning a new language is the
obligatory "Hello, world!" program. Having already considered the
<a href="http://blog.percipientstudios.com/2009/4/11/anatomy-of-an-umbraco-xslt-file.aspx">anatomy
of an umbraco XSLT file</a> it is time to take make our first
umbraco macro following this <a
href="http://en.wikipedia.org/wiki/Hello_world_program"
target="_blank">long-standing and useful tradition</a>.</p>

<p>For this exercise I am using <a href="http://www.umbraco.org"
target="_blank">umbraco</a> 4.0.1 with the Runway package
installed.</p>

<p>&nbsp;</p>

<h2>Create an XSLT macro and insert it into a template</h2>

<h3>Create a HelloWorld XSLT File</h3>

<ol>
<li>In the <strong>Developer</strong> section of umbraco,
right-click the <strong>XSLT Files</strong> item</li>

<li>Select the <strong>Create</strong> menu, as shown below:<br />
<img title="HelloWorld-create xslt menu"
alt="HelloWorld-create xslt menu"
src="http://blog.percipientstudios.com/media/833/WindowsLiveWriter_HelloWorldin12linesofxslt_123F8_HelloWorld-create%20xslt%20menu_2.png" /></li>

<li>Specify the Filename as <strong>HelloWorld</strong>, use the
<strong>Clean</strong> template, and leave the <strong>Create
macro</strong> box checked, then click the Create button, as shown
below:<br />
<img title="HelloWorld-create macro dialog"
alt="HelloWorld-create macro dialog"
src="http://blog.percipientstudios.com/media/843/WindowsLiveWriter_HelloWorldin12linesofxslt_123F8_HelloWorld-create%20macro%20dialog_2.png" /></li>
</ol>

<h3>Add the Hello World macro to the Homepage template</h3>

<p>Now that we have an clean XSLT macro we need to insert it into a
page to see its output. You can add macros directly in a template
or within a Richtext Editor. We'll work with the Runway Homepage
template here and discuss macros in the Richtext Editor (RTE)
another time.</p>

<ol>
<li>In the <strong>Settings</strong> section of umbraco, expand the
<strong>Templates</strong> item</li>

<li>Select the <strong>Runway Homepage</strong> template as shown
below:<br />
<img title="HelloWorld-runway homepage template 01"
alt="HelloWorld-runway homepage template 01"
src="http://blog.percipientstudios.com/media/853/WindowsLiveWriter_HelloWorldin12linesofxslt_123F8_HelloWorld-runway%20homepage%20template%2001_2.png" /></li>

<li>Add a <strong>new line</strong> below the "content" div, as
shown below:<br />
 

<pre class="brush: csharp; gutter: false;">
    &lt;div id="content" class="frontPage"&gt;

        &lt;umbraco:Item runat="server" field="bodyText"/&gt;
    &lt;/div&gt;
</pre>
</li>

<li>Place the cursor on the empty line and click the <strong>Insert
Macro</strong> icon (<span><img
title="HelloWorld-insert macro icon"
alt="HelloWorld-insert macro icon"
src="http://blog.percipientstudios.com/media/863/WindowsLiveWriter_HelloWorldin12linesofxslt_123F8_HelloWorld-insert%20macro%20icon_2.png" /></span>)</li>

<li>Select the <strong>Hello World</strong> macro and click the
<strong>OK</strong> button, as shown below:<br />
<img title="HelloWorld-Insert macro dialog"
alt="HelloWorld-Insert macro dialog"
src="http://blog.percipientstudios.com/media/873/WindowsLiveWriter_HelloWorldin12linesofxslt_123F8_HelloWorld-Insert%20macro%20dialog_2.png" /></li>

<li>The Runway Homepage template should now contain the Hello World
macro, as shown below:<br />
 

<pre class="brush: csharp; gutter: false;">
    &lt;div id="content" class="frontPage"&gt;
        &lt;umbraco:Macro Alias="HelloWorld" runat="server"&gt;&lt;/umbraco:Macro&gt;
        &lt;umbraco:Item runat="server" field="bodyText"/&gt;
    &lt;/div&gt;
</pre>
</li>

<li><strong>Save</strong> the Runway Homepage template by clicking
the Save icon ( <span><img title="HelloWorld-save icon"
alt="HelloWorld-save icon"
src="http://blog.percipientstudios.com/media/883/WindowsLiveWriter_HelloWorldin12linesofxslt_123F8_HelloWorld-save%20icon_2.png" /></span>)</li>
</ol>

<h3>View the homepage</h3>

<p>If you view the homepage in your browser you'll be disappointed
because there is no "Hello, world!" displayed.</p>

<p><img title="HelloWorld-homepage with no output"
alt="HelloWorld-homepage with no output"
src="http://blog.percipientstudios.com/media/893/WindowsLiveWriter_HelloWorldin12linesofxslt_123F8_HelloWorld-homepage%20with%20no%20output_2.png" /></p>

<p>As you may have noticed, we never actually added anything to the
XSLT to display our message. All we've done so far is create a
clean XSLT file and added the macro to the homepage template. These
are important steps that you'll repeat many, many times. But how do
we get some text output to display?</p>

<p>&nbsp;</p>

<h2>What you type is what you get with XSLT</h2>

<h3>Greet the world with XSLT</h3>

<p>We've already discussed the various <a
href="http://blog.percipientstudios.com/2009/4/11/anatomy-of-an-umbraco-xslt-file.aspx">parts of an
XSLT file</a> so in this article we'll spend our time focusing on
one thing: <strong>How can I get my XSLT macro to output text so I
can see it?</strong></p>

<p>The most important thing to remember about XSLT is that
<strong>what you type is what you get</strong>. <em>(unless you
type an xsl: tag, but we'll talk about that in other
posts)</em></p>

<ol>
<li>In the <strong>Developer</strong> section of umbraco, expand
the <strong>XSLT Files</strong> item</li>

<li>Select the <strong>HelloWorld.xslt</strong> file</li>

<li>Edit the template by typing in the Hello, world! text we want
to display, as shown below:<br />
 

<pre class="brush: csharp; gutter: false;">
&lt;xsl:template match="/"&gt;
    Hello, world!
&lt;/xsl:template&gt;
</pre>
</li>
</ol>

<p>Now when you <strong>view the homepage</strong> in your browser
you'll greet the world.</p>

<p><img title="HelloWorld-homepage with raw output"
alt="HelloWorld-homepage with raw output"
src="http://blog.percipientstudios.com/media/903/WindowsLiveWriter_HelloWorldin12linesofxslt_123F8_HelloWorld-homepage%20with%20raw%20output_2.png" /></p>

<h3>Include HTML codes as well as text</h3>

<p>Remember, what you type is what you get with XSLT. And that
includes HTML tags as well. Here are some examples:</p>

<p><strong>Paragraph text</strong><br />
</p>

<pre class="brush: csharp; gutter: false;">
&lt;xsl:template match="/"&gt;
    &lt;p&gt;Hello, world!&lt;/p&gt;
&lt;/xsl:template&gt;
</pre>

<p><strong>Heading</strong><br />
</p>

<pre class="brush: csharp; gutter: false;">
&lt;xsl:template match="/"&gt;
    &lt;h2&gt;Hello, world!&lt;h2&gt;
&lt;/xsl:template&gt;
</pre>

<p><strong>Bold and italic</strong><br />
</p>

<pre class="brush: csharp; gutter: false;">
&lt;xsl:template match="/"&gt;
    &lt;em&gt;Hello,&lt;/em&gt; &lt;strong&gt;world!&lt;/strong&gt;
&lt;/xsl:template&gt;
</pre>

<p><strong>List with a custom class</strong><br />
</p>

<pre class="brush: csharp; gutter: false;">
&lt;xsl:template match="/"&gt;
    &lt;ul class="stylish"&gt;
        &lt;li&gt;Hello, &lt;/li&gt;
        &lt;li&gt;world!&lt;/li&gt;
        &lt;li&gt;Hello, &lt;/li&gt;
        &lt;li&gt;world!&lt;/li&gt;
    &lt;/ul&gt;
&lt;/xsl:template&gt;
</pre>

<p>&nbsp;</p>

<h2>Conclusion</h2>

<p>Congratulations, you have successfully created your first XSLT
macro in umbraco!</p>

<p>As with all Hello, world! exercises, this one is very basic. In
future articles we'll build on these essential steps to perform
more interesting activities.</p>

<p>For now, I want you to remember two things from this exercise.
First, the steps to create an XSLT macro and then insert that macro
into a template. Second, that what you type in XSLT is what you get
out of XSLT.</p>]]></content:encoded></item><item><title>Anatomy of an umbraco XSLT file</title><link>http://blog.percipientstudios.com/2009/4/11/anatomy-of-an-umbraco-xslt-file.aspx</link><pubDate>Sat, 11 Apr 2009 10:05:32 GMT</pubDate><guid>http://blog.percipientstudios.com/2009/4/11/anatomy-of-an-umbraco-xslt-file.aspx</guid><description>
&lt;p&gt;XSLT (e&lt;strong&gt;X&lt;/strong&gt;tensible &lt;strong&gt;S&lt;/strong&gt;ylesheet
&lt;strong&gt;L&lt;/strong&gt;anguage &lt;strong&gt;T&lt;/strong&gt;ransformation) is used
to transform XML into other formats, such as (x)HTML. In this
series of articles you'll learn how to create umbraco macros with
XSLT. This is the first article in that series.&lt;/p&gt;

&lt;p&gt;Before diving in and starting to write an XSLT macro, let's take
a moment to understand the anatomy of an umbraco XSLT file.
Understanding each of the lines in that make up the structure or
&quot;anatomy&quot; of an XSLT file will give you confidence and guidance as
you develop your XSLT skills.&lt;/p&gt;
</description><author>info@percipientstudios.com (Douglas Robar)</author><content:encoded><![CDATA[ <p>XSLT (e<strong>X</strong>tensible <strong>S</strong>ylesheet
<strong>L</strong>anguage <strong>T</strong>ransformation) is used
to transform XML into other formats, such as (x)HTML. In this
series of articles you'll learn the basics of using XSLT for
creating umbraco macros. This is the first post in that series.</p>
<p>When you create a clean XSLT macro in umbraco 4 you see the
following template code (some indenting added for increased
clarity):</p>
<pre class="brush: xml;">
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE xsl:stylesheet [ &lt;!ENTITY nbsp "&amp;#x00A0;"&gt; ]&gt;
&lt;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"
    exclude-result-prefixes="msxml umbraco.library"&gt;
    
    &lt;xsl:output method="xml" omit-xml-declaration="yes"/&gt;
    
    &lt;xsl:param name="currentPage"/&gt;
    
    &lt;xsl:template match="/"&gt;
        &lt;!-- start writing XSLT --&gt;
    &lt;/xsl:template&gt;
    
&lt;/xsl:stylesheet&gt;
</pre>
<p>Before diving in and starting to write an XSLT macro, let's take
a moment to understand the anatomy of an umbraco XSLT file. Though
you won't often need to change any of the default values,
understanding the various parts will be invaluable as we proceed,
and we'll refer back to this article often.</p>
<h2>Line 1: XML version and encoding</h2>
<pre class="brush: xml; gutter: false;">
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
</pre>
<p>Umbraco provides full unicode support for websites, which means
you aren't limited to only ASCII or HTML-encoded characters. For instance, the following unicode characters might be used:
ä ¿ § ¡ ò مرحبًا καλημέρα müjde. To ensure your XSLT macro honors unicode characters you must always specify the XML
encoding.</p>
<p>There is no reason to change this value when using umbraco.</p>
<h2>Line 2: !DOCTYPE and !ENTITY</h2>
<pre class="brush: xml; gutter: false;">
&lt;!DOCTYPE xsl:stylesheet [ &lt;!ENTITY nbsp "&amp;#x00A0;"&gt; ]&gt;
</pre>
<p>XSLT follows all the formatting rules of XML, such as proper
nesting and closing of all tags. Though (x)HTML and XML share many
similarities they are not exactly the same. For instance,
&lt;br&gt; is valid HTML but &lt;br /&gt; is required in
XML/XHTML.</p>
<p>There are five character sequences (or "entities") built-in to
the XSL specification. They are: <strong>&amp;lt; &amp;gt;
&amp;apos; &amp;quot;</strong> and <strong>&amp;amp;</strong> The
!DOCTYPE is only required if you wish to
specify additional entities.</p>
<p>Besides the five built-in entities, HTML makes use of another character sequence very
frequently, the non-breaking space (<strong>&amp;nbsp;</strong>). Line 2 adds this
entity so that you may include non-breaking spaces in your XSLT
macros.</p>
<p>If the entity had not been added you would have to use
<strong>&amp;amp;nbsp;</strong> rather than the more traditional <strong>&amp;nbsp;</strong> in your
macros.</p>
<p>TIP: Remember to use &amp;amp; rather than just the & symbol in your XSLT code. Similarly, when comparing values in XSLT you cannot simply use "5 < 10" but must use "<strong>5 &amp;lt; 10</strong>". This is because the built-in entities resolve the problem of trying to use reserved characters in your XSLT macros. We'll see many examples of this in future articles.</p>
<p>As with line 1, this line rarely needs any modification, though
in extreme cases you might wish to add additional entities.</p>
<h2>Lines 3 and 18: &lt;xsl:stylesheet&gt;
&lt;/xsl:stylesheet&gt;</h2>
<pre class="brush: xml; gutter: false;">
&lt;xsl:stylesheet 
    ...
    ...
&lt;/xsl:stylesheet&gt;
</pre>
<p>These tags enclose the stylesheet instructions themselves. Apart
from the header information in the two lines above, all of your
XSLT will appear inside these tags.</p>
<h2>Lines 4 and 5: XSLT version and namespace</h2>
<pre class="brush: xml; gutter: false;">
    version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
</pre>
<p>Within the opening of the &lt;xsl:stylesheet … &gt; there are a
number of elements specifying details about this stylesheet.</p>
<p>Umbraco uses the <a
href="http://msdn.microsoft.com/en-us/library/ms757858.aspx"
target="_blank">Microsoft XML Parser (MSXML 6.0)</a>, which follows
the <a href="http://www.w3.org/TR/xslt" target="_blank">XSLT 1.0
specification</a>. The XSLT 1.0 specification defines a standard
namespace, which is shown on line 5 and needs no modification.</p>
<p>Notice that all XSL functions are pre-pended with the <strong>xsl:</strong>
prefix label to indicate that they are found in the core XSL
library built into the MSXML parser.</p>
<p>Note: The XSLT 1.0 specification does not support all the XSLT
functions noted at <a
title="http://www.w3schools.com/Xpath/xpath_functions.asp"
href="http://www.w3schools.com/Xpath/xpath_functions.asp">http://www.w3schools.com/Xpath/xpath_functions.asp</a>
(a great reference, by the way!), which lists the full set of
functions available in the newer XSLT 2.0 specification. I'll
discuss which XSLT functions are available in XSLT 1.0 and also
explain how you can work around the limitations of XSLT 1.0 to get
the same effect as the functions in XSLT 2.0 in another
article.</p>
<h2>Lines 6 and 7: Additional namespaces</h2>
<pre class="brush: xml; gutter: false;">
    xmlns:msxml="urn:schemas-microsoft-com:xslt"
    xmlns:umbraco.library="urn:umbraco.library"
</pre>
<p>You can specify additional <a href="http://www.w3.org/TR/REC-xml-names/"
target="_blank">namespaces</a> and gain access to functions
beyond those built into the core XSL namespace. To access these
extra functions you need to add namespaces to the xsl:stylesheet
declaration. This is similar to the "include" or "using" feature of
other languages.</p>
<p>Umbraco references two additional namespaces by default, as
shown in these lines. One for the MSMXL functions (such as
node-set()), and the other for the <strong>umbraco.library</strong> API functions (such
as NiceUrl()). We'll discuss the umbraco.library functions in
detail in another post.</p>
<p>There is no need to change these lines, though you may wish to
include more namespaces to allow you to reference the
functions contained in other XSLT extensions, including those you
create yourself (a topic we'll talk more about in another
article).</p>
<p>Note: Beginning with umbraco 4.0.1, the <a href="http://www.exslt.org" target="_blank">EXSLT library</a> namespace
and functions are also referenced by default, making it easier to
use those extended functions within your umbraco macros. The full xsl:stylesheet declaration
is shown below (some indenting and line breaks added for
clarity):</p>
<pre class="brush: xml; gutter: false;">
    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:Exslt.ExsltCommon="urn:Exslt.ExsltCommon" 
    xmlns:Exslt.ExsltDatesAndTimes="urn:Exslt.ExsltDatesAndTimes" 
    xmlns:Exslt.ExsltMath="urn:Exslt.ExsltMath" 
    xmlns:Exslt.ExsltRegularExpressions="urn:Exslt.ExsltRegularExpressions" 
    xmlns:Exslt.ExsltStrings="urn:Exslt.ExsltStrings" 
    xmlns:Exslt.ExsltSets="urn:Exslt.ExsltSets"
    exclude-result-prefixes="msxml
        umbraco.library 
        Exslt.ExsltCommon 
        Exslt.ExsltDatesAndTimes 
        Exslt.ExsltMath 
        Exslt.ExsltRegularExpressions 
        Exslt.ExsltStrings 
        Exslt.ExsltSets"
    &gt;
</pre>
<h2>Line 8: Excluding prefixes in the output</h2>
<pre class="brush: xml; gutter: false;">
    exclude-result-prefixes="msxml umbraco.library"&gt;
</pre>
<p>When you include additional namespaces you should also list them
in the exclude-result-prefixes list. Simply list all namespaces
you've included (use the prefix after the xslns:) with a space
between each prefix.</p>
<p>You only need to modify this line if you include additional
namespaces.</p>
<h2>Line 10: XSL output method</h2>
<pre class="brush: xml; gutter: false;">
    &lt;xsl:output method="xml" omit-xml-declaration="yes"/&gt;
</pre>
<p><strong>This is the line you are most likely to want to change.</strong></p>
<p>By default, umbraco specifies the output method as "xml". This
is fine in most cases. But there is one situation that you may encounter in which you might 
prefer different behavior.</p>
<p>That situation is when you have an empty
tag in the output. When the output method is set to "xml" the tag will be
simplified or collapsed.</p>
<p>For instance, if your XSLT contained the following:</p>
<pre class="brush: xml; gutter: false;">
&lt;div&gt;&lt;/div&gt;
</pre>
<p>The output sent to the browser with <strong>method="xml"</strong> would be:
<pre class="brush: xml; gutter: false;">
&lt;div /&gt;
</pre>
<p>Most browsers will not handle this
gracefully, your CSS styles will not be applied as expected, and
your site may not display correctly.</p>
<p>There are two solutions. One is to include a test in the XSLT to ensure you
never output an empty tag that will collapse. The other is to
change the XSL output method to "html", which will preserve the
expanded tags and not collapse them.</p>
<p>The output sent to the browser with <strong>method="html"</strong> would be:
<pre class="brush: xml; gutter: false;">
&lt;div&gt;&lt;/div&gt;
</pre>
<p>Do be aware that the "html" output method relaxes the
requirements on the output somewhat and this may introduce issues that could 
cause your webpages to fail xhtml validation because of un-closed tags, as 
is appropriate for HTML 4.0 but not XHTML.

According to the XSLT specification at <a
title="http://www.w3.org/TR/xslt#section-HTML-Output-Method"
href="http://www.w3.org/TR/xslt#section-HTML-Output-Method">http://www.w3.org/TR/xslt#section-HTML-Output-Method</a>, you'll find the following:</p>
<p>The html output method should not output an end-tag for empty elements. 
For HTML 4.0, the empty elements are: 
<em>area</em>, <em>base</em>, <em>basefont</em>, <em>br</em>, <em>col</em>, <em>frame</em>, <em>hr</em>, 
<em>img</em>, <em>input</em>, <em>isindex</em>, <em>link</em>, <em>meta</em>, and <em>param</em>.
For example, an element written as &lt;br /&gt; or &lt;br&gt;&lt;/br&gt; in the 
stylesheet should be output as &lt;br&gt;
</p>
<p>A more interesting situation is that the img tag will not have a closing slash with method="html".</p>
<p style="text-decoration: line-through;">Indeed, <strong>you may wish to set all your XSLT macros to use
method="html"</strong> and reserve method="xml" for special
cases,such as when creating RSS feeds that must be in valid XML
format with collapsed tags.</p>
<p>Because some tags do not get closed when using method="html" I recommend the use of 
method="xml" unless you have a specific reason to use method="html". Just be sure to avoid
empty tags that would collapse and potentially break your site's css rendering.
</p>

<p>Only in very rare and special cases would you want to include
the xml declaration (&lt;?xml...?&gt;) in the output, and never for
output used in (x)HTML pages no matter what setting you've used for
the output method.</p>
<h2>Line 12: The currentPage parameter</h2>
<pre class="brush: xml; gutter: false;">
    &lt;xsl:param name="currentPage"/&gt;
</pre>
<p>Unlike traditional XSLT in which the entire content of a single
file is processed and transformed, a website must include some
sense of context.</p>
<p>What page is the website visitor currently viewing? That is what
the currentPage parameter is used for. Of all the pages in your
site, currentPage will tell you which one is being viewed.</p>
<p>The currentPage parameter is automatically populated by umbraco.
It is referenced as $currentPage in your XSLT and you will use it a
lot, as we'll see in future articles.</p>
<h2>Lines 14 to 16: Template match="/"</h2>
<pre class="brush: xml; gutter: false;">
    &lt;xsl:template match="/"&gt;
        &lt;!-- start writing XSLT --&gt;
    &lt;/xsl:template&gt;
</pre>
<p>Templates are a lot like functions() in other languages. They
can be referenced by name (named templates) or they can run
automatically when the xml being processed matches a certain condition
(match templates).</p>
<p>All xml files will have a root node and will match the root or
"/" xpath query. Thus, a match template with match="/" will always
be executed, and executed first because the root node in the XML is
always the first node.</p>
<p>Or, putting it another way, template match="/" is a lot like the
main() or Page_Load() functions in other languages.</p>
<p>We'll discuss xpath as well as match and named templates in
detail in other articles. For now, the important thing to understand
is that any XSLT code you put in the match="/" template will always
be executed when the macro runs.</p>
<h2>Conclusion</h2>
<p>The pre-defined XSLT templates provided by umbraco can be used
"as-is" and few people bother to worry about what all those lines
are doing. You, too, might often do that, focusing your efforts on
line 15 and writing your own XSLT code.</p>
<p>But understanding each of the lines that make up the
structure or "anatomy" of an XSLT file will give you confidence and
guidance as you develop your XSLT skills through this series of
articles. We will look back to these settings in many of the
articles to come.</p>]]></content:encoded></item><item><title>Customizing XSLTsearch</title><link>http://blog.percipientstudios.com/2009/4/7/customizing-xsltsearch.aspx</link><pubDate>Tue, 07 Apr 2009 17:23:50 GMT</pubDate><guid>http://blog.percipientstudios.com/2009/4/7/customizing-xsltsearch.aspx</guid><description>
&lt;p&gt;Most of the modifications people want to make to &lt;a
href=&quot;http://www.percipientstudios.com/xsltsearch.aspx&quot;&gt;XSLTsearch&lt;/a&gt;
have to do with limiting or filtering the nodes being searched.&lt;/p&gt;

&lt;p&gt;As an example, suppose you have a blog and want to exclude blog
comments from the search results. This is easily done with a
one-line addition to the xsltsearch.xslt macro file.&lt;/p&gt;
</description><author>info@percipientstudios.com (Douglas Robar)</author><content:encoded><![CDATA[ <p>Most of the modifications people want to make to <a
href="http://www.percipientstudios.com/xsltsearch.aspx">XSLTsearch</a>
have to do with limiting or filtering the nodes being searched.</p>
<p>As an example, suppose you have a blog and want to exclude blog
comments from the search results. This is easily done with a
one-line addition to the xsltsearch.xslt macro file.</p>
<p>Search for <strong>umbracoNaviHide</strong> and you'll find the
possibleNodes variable in the search template. <strong>This is
where most of the modifications you might ever want to make would
be made.</strong></p>
<p>The search template looks like this (XSLTsearch 2.8):</p>
<pre class="brush: xml; gutter: false;">
&lt;xsl:template name="search"&gt;
    &lt;!-- Perform the search on the appropriate nodeset and display the output --&gt;
    &lt;xsl:param name="items"/&gt;
    &lt;!-- reduce the number of nodes --&gt;
    &lt;xsl:variable name="possibleNodes" select="$items/descendant-or-self::node[
         string(data [@alias='umbracoNaviHide']) != '1'
         and count(attribute::id)=1 
         and (umbraco.library:IsProtected(@id, @path) = false()
         or umbraco.library:HasAccess(@id, @path) = true())
        ]"/&gt;
    ...
</pre>
<p>&nbsp;</p>
<p>As you can see, the search template that gets all the possible
nodes that will be searched. In our example, we want to remove from
the search any <strong>BlogPostComment</strong> nodes. We'll do
that by checking the <strong>@nodeTypeAlias</strong>.</p>
<p>The modified xsltsearch.xslt file that excludes blog post
comments would look like:</p>
<pre class="brush: xml; gutter: false;">
    &lt;!-- reduce the number of nodes --&gt;
    &lt;xsl:variable name="possibleNodes" select="$items/descendant-or-self::node[
         string(data [@alias='umbracoNaviHide']) != '1'
         and @nodeTypeAlias != 'BlogPostComment'
         and count(attribute::id)=1 
         and (umbraco.library:IsProtected(@id, @path) = false()
         or umbraco.library:HasAccess(@id, @path) = true())
        ]"/&gt;
    ...
</pre>
<p>This same technique could be used to search within certain
document types (rather than to exclude certain document types as we
did above). To search only within umbraco content nodes of homepage
and webpage document types we would modify the possibleNodes
variable like this:</p>
<pre class="brush: xml; gutter: false;">
    &lt;!-- reduce the number of nodes --&gt;
    &lt;xsl:variable name="possibleNodes" select="$items/descendant-or-self::node[
         string(data [@alias='umbracoNaviHide']) != '1'
         and (
            @nodeTypeAlias = 'homepage'
            or @nodeTypeAlias = 'webpage'
            )
         and count(attribute::id)=1 
         and (umbraco.library:IsProtected(@id, @path) = false()
         or umbraco.library:HasAccess(@id, @path) = true())
        ]"/&gt;
    ...
</pre>
<p>Or perhaps you have created your own document type property
called&nbsp; 'searchHide' rather than assuming that any page that
does not appear in the navigation should not appear in the search
results either. If so, you would simply change the umbracoNaviHide
alias to that of your property:</p>
<pre class="brush: xml; gutter: false;">
    &lt;!-- reduce the number of nodes --&gt;
    &lt;xsl:variable name="possibleNodes" select="$items/descendant-or-self::node[
         string(data [@alias='searchHide']) != '1'
         and count(attribute::id)=1 
         and (umbraco.library:IsProtected(@id, @path) = false()
         or umbraco.library:HasAccess(@id, @path) = true())
        ]"/&gt;
    ...
</pre>
<p>&nbsp;</p>
<p>Though these examples are simple, more advanced modifications
can be handled in the same way.</p>
<p>For instance, it would be a small matter to create a custom
search form that included checkboxes for the areas or docTypes of
your site to search (such as FAQs, News, Support, Products, etc.).
You could simply add a macro parameter and pass in the
nodeTypeAlias(es) according to the user's selection rather than
hard-coding them as we've done here.</p>
<p>Many websites will not need to modify <a
href="http://www.percipientstudios.com/xsltsearch.aspx">XSLTsearch</a>
because of the many built-in options it provides; but it is nice to
know that it is so easy to customize <a
href="http://www.percipientstudios.com/xsltsearch.aspx">XSLTsearch</a>
to meet your site's unique needs if you need to.&nbsp;</p>
]]></content:encoded></item></channel></rss>
