• Get the Flash Player to see the slideshow.
  • Categories

  • Authors

  • Great Quotes

    Everything should be as simple as possible, but not simpler. — Albert Einstein

Get in touch...

To have a chat about
your CMS needs...

Call us 0207 193 2014
or
Email us on

Posts Tagged ‘LiveSite’

XSL:Sort by Date, Organise by Type

Monday, March 2nd, 2009

In this example, we have a collection of material which we want to make available to users: whitepapers, articles, tips etc.  We want to group these by material and show the relevant subheading when this changes, but avoid redisplaying the heading if it remains the same, say:

Whitepaper

Article

As per other examples, the key to doing this is to ensure we have the collection sorted correctly before we consider displaying them:

<xsl:apply-templates select="[list of items being processed]">
<xsl:sort select="./type"/>
<xsl:sort order="descending" select="substring(./created,7,4)"/>
<xsl:sort order="descending" select="substring(./created,4,2)"/>
<xsl:sort order="descending" select="substring(./created,1,2)"/>
</xsl:apply-templates>

At this point we have a set of items in ascending alphabetical types, reverse ordered by date.

We then call the familiar block to begin processing.

There is now some logic required here to say, if repeat type do not display, if a new type display.

In a scripting language, the obvious solution is to store the type in a variable, and do something if the new type differs from the last stored type.

Restrictions on <xsl:variable> mean we cannot do this.

Loosely, in XSLT position() translates to count [forwards].  XLST has a function that is similar to ‘count backwards’ which is preceding-sibling [OK, it means invert the node set and count forwards, but you get the idea].

Therefore by saying preceding-sibling::*[1]/type XPath expression say “go to the first preceding sibling, then get its type element’s contents” and the expression provides a ready means of testing “is the current value the same as the last one”.

It is worth pointing out that this is a sophisticated function, there are similar ones such as following-sibling, preceding, ancestor, or ancestor-or-self which may be more appropriate to the use required.

It is also important to note the use of ‘*[1]/type’.  The * is a wildcard and this would not work if there were multiple child elements type within the given element.  The [1] is important too as this means go-back-one: or, more accurately, reverse the list and read the next … If the [1] was omited, the expression would say, look backwards anywhere in the list.

Finally, reading backwards would return a null value if the top of the list was reached, so a failsafe is required to make sure we are not at the top of the list.

<xsl:choose>
<xsl:when test="position() = 1">
<!-- display the type-->
<xsl:value-of select="./type"/>
</xsl:when>
<xsl:when test="position() &gt; 1">
<!-- only read backwards now we have read at least one record -->
<xsl:if test="./type != preceding-sibling::*[1]/type">
<!-- only if the type has changed-->
<xsl:value-of select="./type"/>
</xsl:if>
</xsl:when>
</xsl:choose>

XSL:Sort By Date, Limit Returned Results

Monday, March 2nd, 2009

In an accompanying article, a simple method to sort by date was introduced.

Normally it is desirable to limit the number of results shown.

There are various complex ways of doing this posted on other sites, the fundamental problem being that <xsl:variable> works as a constant in practice, i.e set only once.

Trying to implement a counter as per scripting languages becomes difficult – although not impossible – so rather than fight against the restrictions XSLT gives, better to use the inbuilt position() function, which will tell you how far it has progressed along the current record set.

Provided all the select criteria have been applied to the record set FIRST, the position() function will effectively map to counter.

To complete the process, set a global variable (probably based on a Datum) to fix the displayed items

<xsl:variable name="x-rows" select="//Datum[@Name='FixLimit']"/>
 
<xsl:template match="/">
 
<xsl:apply-templates select=”[some repeating datum]“&gt;
<xsl:sort order=”descending” select=”substring(//somedate,7,4)> <!-- year->
<xsl:sort order=”descending” select=”substring(//somedate,4,2)> <!-- month-->
<xsl:sort order=”descending” select=”substring(//somedate,1,2)> <-- day-->
 
</xsl:apply-templates>

Now in the add a ‘count’ test for each time the executes:

<xsl:template match=”[match repeating datum]>
   <xsl:if test="position() &lt;= $x-rows">
   ...
   </xsl:if>
</xsl:template>

to stop processing once the row limit has been reached.

XSL:Sort By Date

Monday, March 2nd, 2009

The following  should do the work

<xsl:apply-templates select="[some repeating datum]">
<xsl:sort order="descending" select="substring(//somedate,7,4)"> <!-- year-->
<xsl:sort order="descending" select="substring(//somedate,4,2)"> <!-- month-->
<xsl:sort order="descending" select="substring(//somedate,1,2)"> <!-- day-->
</xsl:apply-templates>

This assumes the date is in the form dd/mm/yyyy: the seperators could be different as they are ignored anyway based on the substring.

The important thing to realise here is that the <xsl:sort> functions do not do anything APART from sort, so there is nothing to see at this point if debugging

The work is done in a receiving

<xsl:template match="[match repeating datum]">
 
...
 
</xsl:template>

The ensures items are delivered to this block in the correct order, what is displayed is determined in the section

XSL Extract File Suffix, Convert to Uppercase, Display

Monday, March 2nd, 2009
<xsl:value-of
select="translate(substring-after(/Properties/Data/Datum[@Name='filename'],'.'),'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ')"/>