XSLT POWERED MACROS

Using XSLT can be rather daunting if it's a new language for you. But, once you have a grasp of how to use it, you can whip up custom navigation, RSS feeds, depicted calendars, product lists, and much more with great ease. The good news is that Umbraco comes with a set of predefined templates that you can use to generate standard output such as navigation and sitemaps. What's more is that they serve as a powerful learning tool to get you started on creating more advanced output and tailoring the stylesheets to your needs.

About XSLT

If you're an avid XSL developer you can skip this section because it covers the bare-bone basics of what XSLT is and how it applies to Umbraco. XSLT stands for Extensible Stylesheet Language Transformation and is made up of XSL. XSL is basically a way to render structured data, in the form of XML elements, to the browser. There are a number of other ways to parse XML elements but we won't get into those here; however, you can find out how to parse these elements in Beginning XSLT and XPath: Transforming XML Documents and Data (Wiley, 2009).

image Microsoft .NET uses the XSL 1.0 specification. This means that you cannot take advantage of more advanced functions and methods presented in XSL 2.0.

The most important part of learning and using XSLT with Umbraco is understanding how you traverse the cached XML content tree using the XML Path Language, aka XPath. Inspecting and learning the structure of the XML cache will allow you to drill down and specify exactly what parts of the content structure you are looking for. The XML cache file can be found in ~/App_Data/umbraco.config.

In addition, Umbraco uses a parameter, currentPage, that is always available to you. This parameter holds the entire nodeset of the current node where the template is going to be executed, which in turn also includes all child nodes and grandchild nodes. From a performance standpoint this is great because you are not constantly querying the entire XML nodeset from memory.

Finally, you should know that Umbraco comes with something called an XSLT Extension Library, which allows you to easily do things like formatting dates, split strings, truncate strings, and a whole lot more. Of course, on top of that you can also leverage the EXSLT extensions that are part of the XSL parsing libraries in .NET.

All these important XSLT features—XPath, currentPage, and the XSLT Extension Library—are thoroughly examined through various examples, both in the remaining portions of this chapter, as well as throughout the rest of the book.

image For more details on XSL and the W3C specification, please visit http://www.w3c.org/TR/xsl.

image XSLT macros can ONLY access published content because it looks at the in-memory XML cache found in ~/App_Data/umbraco.config. This XML structure does not include unpublished nodes. To access unpublished content, you have to use either .NET driven macros, DLR (Python and Ruby) driven macros, or add XSLT extensions to access the data from the database.

Using the Built-in XSLT Templates

As mentioned earlier, Umbraco ships with a number of XSLT templates to get you going. When creating a new XSLT file, as shown in Figure 5-6, you can choose to base your new file on one of the templates listed in Table 5-3.

FIGURE 5-6

image

TABLE 5-3: Built-in XSLT Templates

image

image

To get an idea of what a template looks like, see Listing 5-1, which shows how the Breadcrumb template is created. Bolded portions of the template show the critical parts of the XSLT file that specify what pages to select and also shows the use of an XSLT extension method from the umbraco.library extensions method library, covered in detail in “Using XSLT Extensions” later in this chapter.

LISTING 5-1: Breadcrumb.xslt

image
<?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: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 “>

  <xsl:output method=“xml” omit-xml-declaration=“yes”/>

  <xsl:param name=“currentPage”/>

  <xsl:variable name=“minLevel” select=“1”/>

  <xsl:template match=“/”>

    <xsl:if test=“$currentPage/@level &gt; $minLevel”>
      <ul>
        <xsl:for-each select=“$currentPage/ancestor::* [@level &gt; $minLevel
 and string(umbracoNaviHide) != ‘1’]”>
          <li>
            <a href=“{umbraco.library:NiceUrl(@id)}”>
              <xsl:value-of select=“@nodeName”/>
            </a>
          </li>
        </xsl:for-each>
        <!-- print currentpage -->
        <li>
          <xsl:value-of select=“$currentPage/@nodeName”/>
        </li>
      </ul>
    </xsl:if>
  </xsl:template>
</xsl:stylesheet>

image To save an XSLT file in the Umbraco backoffice you can use the commonly used keyboard combination, Ctrl+S.

The following steps provide a step-by-step walkthrough of Listing 5-1.

  1. The template starts at the current node by referencing the currentPage parameter and traverses up the tree using the ancestor axes to start at the top most parent of this node.
  2. The XPath statement is further refined by filtering with the @level attribute, which tells the loop where to start in the hierarchy.
  3. The XPath statement makes sure to only include nodes where the umbracoNaviHide property is not set to a value of 1 (or true as it is meant in this case).
  4. Inside the loop you output an HTML list item, and inside that is a bit of magic, namely a call to one of the afore mentioned XSLT extension methods. See the next section for details on how to insert and use extension methods.
  5. The output that the user will see is set to be the @nodeName, which is an attribute of the current node and represents the Name that you give the node when it is first created, as seen in Figure 5-7.

    FIGURE 5-7

    image

  6. Finally, and outside of the <xsl:for-each /> loop, you output the current node to indicate the page that the user is presently viewing.

Creating an XSLT Macro

Now that you know the inner workings of this template, let's see how to create this from scratch.

  1. Navigate to the Developer section.
  2. Right-click XSLT Files and click the Create menu option.
  3. Enter SiteBreadcrumb in the Filename field and choose Breadcrumb as the template in the dropdown, as shown in Figure 5-8. Leave the Create Macro option selected (not shown here, but easily visible on your screen).

    FIGURE 5-8

    image

  4. Click the Create button.

image You can now reload the Macros node in the Developers section and see that a Macro was added named Site Breadcrumb, with the newly created XSLT file pre-selected.

So, now what? You have a terrific little macro but need somewhere to put it. The appropriate location to include this macro is in one of your templates, seeing as you want this displayed on all your internal pages and it is context sensitive. The bolded code in Listing 5-2 shows the syntax for including a macro in your template. If you installed Runway during installation in Chapter 1, the best template to place this macro in is Runway Textpage, as shown in Listing 5-2.

LISTING 5-2 RunwayTextpage.master

image
<%@ Master Language=“C#” MasterPageFile=“~/masterpages/RunwayMaster.master”
AutoEventWireup=“true” %>
<asp:Content ContentPlaceHolderID=“RunwayMasterContentPlaceHolder”
runat=“server”>
    <div id=“content”>
        <umbraco:Macro Alias=“SiteBreadcrumb”
runat=“server”></umbraco:Macro>
             <div id=“contentHeader”>
            <h2><umbraco:Item runat=“server” field=“pageName”/></h2>
        </div>
        <umbraco:Item runat=“server” field=“bodyText” />
    </div>
    <div id=“subNavigation”></div>
</asp:Content>

There's an easier way to insert the macro tag than typing it in there. To use the built-in Insert Macro tool, follow these steps.

  1. Navigate to the Runway Textpage template in the Settings section.
  2. Place the cursor where you want to insert the macro.
  3. Click the Insert Macro button as shown in Figure 5-9.

    FIGURE 5-9

    image

  4. Select the macro to insert it and then click the OK button.

image If you've specified macro parameters, clicking the OK button reveals a properties screen asking you to fill in the various fields associated with the macro parameters before the tag is inserted into the template.

Using XSLT Extensions to Make Macros Richer

Using XSLT extensions will provide you with a whole new set of tools to render and work with content nodes, custom data, and other standard features of .NET. Umbraco ships with the following libraries:

  • Exslt.ExsltCommon
  • Exslt.ExsltDatesAndTimes
  • Exslt.ExsltMath
  • Exslt.ExsltRegularExpressions
  • Exslt.ExsltSets
  • Exslt.ExsltStrings
  • umbraco.library

The combination of all these libraries gives you access to hundreds of extension methods to make output of data easier. For the purposes of this book, however, we are going to cover the methods provided in the umbraco.library method library. The Umbraco library contains methods that allow you to access Umbraco data and functions specific to working with Umbraco pages, data types, and document types. It's beyond the scope of this book to describe each and every method in the umbraco.library library, so in Table 5-4 you get an overview of what the most widely used methods can do for you.

image You can easily generate your own XSLT extensions library by creating a public class with public static methods in it. For an example of this, please refer to Chapter 12.

TABLE 5-4: Most Popular XSLT Extension Methods

image

image

To utilize any of the methods in Table 5-4, and the rest of the available methods, simply follow these steps:

  1. Open your XSLT file in the backoffice editor by navigating to the Developer section and expanding the XSLT Files node by clicking the arrow.
  2. Place the cursor in the template where you want to insert the library method.
  3. Click the Insert xsl:value-of button as shown in Figure 5-10.

    FIGURE 5-10

    image

  4. Click the Get Extension button.
  5. Select umbraco.library in the first drop-down list.
  6. Select the method to use in the second drop-down list.
  7. If the method takes arguments, you are asked to enter them after selecting the method to use, as shown in Figure 5-11.

FIGURE 5-11

image

Going Further with XSLT

Believe it or not, what you've seen so far are the basics. XSLT can get a lot more advanced and complicated. Again, it is not the job of this book to teach you all there is to know about XSLT, but to make your journey a tad more useful, the examples in Listings 5-3 and 5-5 take you through some more common usages of XSLT within Umbraco.

Output an Image from the Media Library

Media items, such as images, files, and folders, can be retrieved using the GetMedia XSLT extension that you were introduced to in the previous section. However, GetMedia returns a nodeset so it's not as simple as just calling the method. In addition, you also need to specify what information you want out of the nodeset. Listing 5-3 shows you how this is done. The steps that follow walk you through the process.

image To select a media item to display, simply add the Media Picker data type to one of your document types and you can target a file, folder, or image using that data type when editing a node.

The Media Picker data type stores the chosen media item using the associated node Id for the media item.

  1. In the Developer section, create a new XSLT file and name it MediaOutput, based on the Clean template, and select the Create Macro check box, as shown in Figure 5-12.
  2. Navigate to the macro details and add a new parameter in the Parameter tab:
    • Alias: PropertyAlias
    • Name: Field Name
    • Type: Text

    FIGURE 5-12

    image

  3. Add the code in Listing 5-3, or 5-4 if you are running Umbraco 4.0.x, to your XSLT file.

LISTING 5-3: MediaOutput-4.5.xslt

image
<?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: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 “>


    <xsl:output method=“xml” omit-xml-declaration=“yes”/>

    <xsl:param name=“currentPage”/>
    <xsl:variable name=“propertyAlias” select=“/macro/propertyAlias”/>
    <xsl:variable name=“propertyValue” select=“$currentPage/*
              [name()=$propertyAlias]”/>

    <xsl:template match=“/”>
        <!-- check to make sure the property value that we pass in
             is not empty -->
        <xsl:if test=“$propertyValue!=‘’”>
            <!-- localize the media nodeset into a shorter variable
                 name for readability -->
            <xsl:variable name=“mediaItem”
select=“umbraco.library:GetMedia($propertyValue, ‘false’)”/>
            <xsl:if test=“$mediaItem!=‘’”>
                <img>
                    <xsl:attribute name=“src”>
                        <xsl:value-of select=“$mediaItem/umbracoFile” />
                    </xsl:attribute>
                    <xsl:attribute name=“width”>
                        <xsl:value-of select=“$mediaItem/umbracoWidth” />
                    </xsl:attribute>
                    <xsl:attribute name=“height”>
                        <xsl:value-of select=“$mediaItem/umbracoHeight” />
                    </xsl:attribute>
                    <xsl:attribute name=“alt”>
                        <xsl:value-of select=“$mediaItem/@nodeName” />
                    </xsl:attribute>
                </img>
            </xsl:if>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

LISTING 5-4: MediaOutput-4.0.x.xslt

image
<?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: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 “>


    <xsl:output method=“xml” omit-xml-declaration=“yes”/>

    <xsl:param name=“currentPage”/>
    <xsl:variable name=“propertyAlias” select=“/macro/propertyAlias”/>

    <xsl:template match=“/”>
        <!-- check to make sure the property value that we
             pass in is not empty -->
        <xsl:if test=“$propertyAlias!=‘’”>
            <!-- localize the media nodeset into a shorter variable
                 name for readability -->
            <xsl:variable name=“mediaItem”
select=“umbraco.library:GetMedia($currentPage/data [@alias=$propertyAlias],
 ‘false’)”/>
            <xsl:if test=“$mediaItem!=‘’”>
                <img>
                    <xsl:attribute name=“src”>
                        <xsl:value-of select=“$mediaItem/data
[@alias=‘umbracoFile’]” />
                    </xsl:attribute>
                    <xsl:attribute name=“width”>
                        <xsl:value-of select=“$mediaItem/data
[@alias=‘umbracoWidth’]” />
                    </xsl:attribute>
                    <xsl:attribute name=“height”>
                        <xsl:value-of select=“$mediaItem/data
[@alias=‘umbracoHeight’]” />
                    </xsl:attribute>
                    <xsl:attribute name=“alt”>
                        <xsl:value-of select=“$mediaItem/@nodeName” />
                    </xsl:attribute>
                </img>
            </xsl:if>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

Grouping Output by Date

Often times you will want to output lists of information in a certain order and/or grouping. One great example of this is the Event document type that you added in Chapter 3. On the event details page, you may want to output all of the events grouped by month, as shown in the following steps:

  1. In the Developer section, create a new XSLT file and name it EventOutputGroupedByMonth, based on the Clean template, and select the Create Macro check box.

    image See “Creating an XSLT Macro” earlier in this chapter for detailed steps on how to create an XSLT file and associated macro.

  2. Add the code in Listing 5-5, or 5-6 if you are running Umbraco 4.0.x, to your XSLT file.

LISTING 5-5: EventOutputGroupedByMonth-4.5.xslt

image
<?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: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”
xmlns:scandia.library=“urn:scandia.library”
  exclude-result-prefixes=“msxml umbraco.library Exslt.ExsltCommon
Exslt.ExsltDatesAndTimes Exslt.ExsltMath Exslt.ExsltRegularExpressions
Exslt.ExsltStrings Exslt.ExsltSets scandia.library “>

  <xsl:output method=“html” omit-xml-declaration=“yes”/>

  <xsl:param name=“currentPage”/>

  <!-- Local variables -->
  <xsl:variable name=“documentTypeAlias” select=“string(‘Event’)”/> <!-- the
specific document type that we're are looking for -->
  <!-- store the nodes into a localized and sorted nodeset -->
  <xsl:variable name=“data”>
    <xsl:for-each select=“$currentPage/descendant-or-self::* [name() =
$documentTypeAlias and string(umbracoNaviHide) != ‘1’]”>
      <xsl:sort select=“.” data-type=“text” />
      <xsl:copy-of select=“.”/>
    </xsl:for-each>
  </xsl:variable>
  <!-- create a key that we can use to “look up” data based on in our
       loop below and match only the Event document type -->
  <xsl:key name=“nodes-by-MMMM” match=“Event”
use=“umbraco.library:FormatDateTime(eventStartDateTime,‘MMMM’)”/>

  <xsl:template match=“/”>
    <!-- create a nodeset of the data we stored earlier and pick out
         the ‘Event’ nodes, then group them by the full month string -->
    <xsl:for-each select=“msxml:node-set($data)/Event [count(. | key(‘nodes-
by-MMMM’, umbraco.library:FormatDateTime(eventStartDateTime,‘MMMM’))[1]) =
1]”>
      <xsl:sort select=“eventStartDateTime” order=“descending” />

      <div class=“news-month”>
        <div class=“heading”>
          <xsl:value-of
select=“umbraco.library:FormatDateTime(eventStartDateTime,‘MMM yyyy’)”/>
        </div>
        <ul class=“ctr-events”>
        <!-- This inner loop simply outputs the nodes that match the selected
             key we specified outside of this template -->
          <xsl:for-each select=“key(‘nodes-by-MMMM’,
umbraco.library:FormatDateTime(eventStartDateTime,‘MMMM’))”>
              <li>
                <!-- create an anchor element so we can link to the
                     event details -->
                <xsl:element name=“a”>
                  <xsl:attribute name=“href”>
                    <xsl:value-of select=“umbraco.library:NiceUrl(@id)”/>
                  </xsl:attribute>
                  <xsl:value-of select=“eventTitle”/>
                </xsl:element>
                <div class=“fulldate”>
                  <xsl:value-of
select=“umbraco.library:FormatDateTime(eventStartDateTime,‘MMM dd, yyyy’)”/>
                </div>
              </li>
          </xsl:for-each>
        </ul>
      </div>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

LISTING 5-6: EventOutputGroupedByMonth-4.0.x.xslt

image

<?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: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”
xmlns:scandia.library=“urn:scandia.library”
  exclude-result-prefixes=“msxml umbraco.library Exslt.ExsltCommon
Exslt.ExsltDatesAndTimes Exslt.ExsltMath Exslt.ExsltRegularExpressions
Exslt.ExsltStrings Exslt.ExsltSets scandia.library “>

  <xsl:output method=“html” omit-xml-declaration=“yes”/>

  <xsl:param name=“currentPage”/>

  <!-- Local variables -->
  <xsl:variable name=“documentTypeAlias” select=“string(‘Event’)”/>
  <!-- the specific document type that we‘re are looking for -->

  <!-- store the nodes into a localized and sorted nodeset -->
  <xsl:variable name=“data”>
    <xsl:for-each select=“$currentPage/descendant-or-self::node [string(data
[@alias=‘umbracoNaviHide’]) != ‘1’ and @nodeTypeAlias=$documentTypeAlias]”>
      <xsl:sort select=“.” data-type=“text” />
      <xsl:copy-of select=“.”/>
    </xsl:for-each>
  </xsl:variable>
  <!-- create a key that we can use to “look up” data based on in our
       loop below and match only the Event document type -->
  <xsl:key name=“nodes-by-MMMM” match=“node”
use=“umbraco.library:FormatDateTime(data
[@alias=‘eventStartDateTime’],‘MMMM’)”/>

  <xsl:template match=“/”>
    <!-- create a nodeset of the data we stored earlier and pick out
         the ‘Event’ nodes, then group them by the full month string -->
    <xsl:for-each select=“msxml:node-set($data)[count(. | key(‘nodes-by-MMMM’,
umbraco.library:FormatDateTime(data [@alias=‘eventStartDateTime’],‘MMMM’))[1])
= 1]”>
      <xsl:sort select=“string(data [@alias=‘eventStartDateTime’])”
order=“descending” />

      <div class=“news-month”>
        <div class=“heading”>
          <xsl:value-of select=“umbraco.library:FormatDateTime(data
[@alias=‘eventStartDateTime’],‘MMM yyyy’)”/>
        </div>
        <ul class=“ctr-events”>
          <!-- This inner loop simply outputs the nodes that match the
               selected key we specified outside of this template -->
          <xsl:for-each select=“key(‘nodes-by-MMMM’,
umbraco.library:FormatDateTime(data [@alias=‘eventStartDateTime’],‘MMMM’))”>
              <li>
                <!-- create an anchor element so we can link to the
                     event details -->
                <xsl:element name=“a”>
                  <xsl:attribute name=“href”>
                    <xsl:value-of select=“umbraco.library:NiceUrl(@id)”/>
                  </xsl:attribute>
                  <xsl:value-of select=“data [@alias=‘eventTitle’]”/>
                </xsl:element>
                <div class=“fulldate”>
                  <xsl:value-of select=“umbraco.library:FormatDateTime(data
[@alias=‘eventStartDateTime’],‘MMM dd, yyyy’)”/>
                </div>
              </li>
          </xsl:for-each>
        </ul>
      </div>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

image The above grouping method is known as the Muenchian Method. More on that topic can be found at, http://en.wikipedia.org/wiki/Muenchian_grouping.

For more examples and utilizations of XSLT macros take a look at Chapter 11. In addition to this book, take a look at http://our.umbraco.org, specifically the Projects section, where developers continuously share their solutions with the community.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset