Tuesday, 15 June 2010
Sitecore link fields put /home in the target URL's href
Tuesday, 23 March 2010
How to remove an apostrophe from a string in Sitecore XSLT
<xsl:variable name="apos">'</xsl:variable>
<xsl:variable name="string"
select="sc:Replace( $input, $apos, '' )" />
Friday, 14 August 2009
Write to Sitecore log file from XSLT
In the web.config, define the extension under <xslextensions>:
<extension mode="on"
type="Sitecore.Diagnostics.Log, Sitecore.Kernel"
namespace="http://www.sitecore.net/log"
singleInstance="true" />
Within the XSLT file, add a prefix that matches the namespace you used in the above step:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:sc="http://www.sitecore.net/scReal"
xmlns:dot="http://www.sitecore.net/dot"
xmlns:log="http://www.sitecore.net/log"
exclude-result-prefixes="dot sc log">
The Log class contains a number of overloads for Info, Warn, Error and so on. Some of these expect an exception as a parameter, so we cannot call these direct from XSLT. We can, however match the overloads that expect a string and an object (eg. Warn( String, Object )):
<xsl:value-of select="log:Warn('Warning message', 'Another string... perhaps the name of your rendering file')" />
That's it! Now you can log whatever you like from within your renderings.
Tuesday, 28 July 2009
Enable XSLT IntelliSense within Visual Studio
To enable these autocompletions and more, you need to back up your registry and then run regedit. Within regedit, create a string value called "XsltIntellisense" under "HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\9.0\XmlEditor" key, giving it the value "True". That's it!
Ultimately, I'd like to see full IntelliSense for XSLT in Visual Studio, but this is a good start.
Friday, 16 January 2009
Screen reader friendly phone numbers
By encasing each digit within a <span /> tag, the digits are read out individually. So, (01234) 567890 becomes “left paren zero one two three four right paren five six seven eight nine zero”.
I have written an XSLT template that takes a phone number and applies a <span /> to each digit:
<xsl:template name="DisplayPhoneNumber">
<xsl:param name="position" />
<xsl:param name="phonenumber" />
<xsl:variable name="digit"
select="substring($phonenumber, $position, 1)" />
<xsl:choose>
<xsl:when test="contains('012345678', $digit)">
<span>
<xsl:value-of select="$digit" />
</span>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$digit" />
</xsl:otherwise>
</xsl:choose>
<xsl:if test="$position <
string-length($phonenumber)">
<xsl:call-template name="DisplayPhoneNumber">
<xsl:with-param name="position">
<xsl:value-of select="$position+1" />
</xsl:with-param>
<xsl:with-param name="phonenumber"
select="$phonenumber" />
</xsl:call-template>
</xsl:if>
</xsl:template>
To call the template, pass in the telephone number and prime the starting position using a value of 1:
<xsl:call-template name="DisplayPhoneNumber">
<xsl:with-param name="position" select="'1'" />
<xsl:with-param name="phonenumber"
select="'(01234) 567890'" />
</xsl:call-template>
If you’re using this within Sitecore, you can simply pass in a field value in the usual way:
<xsl:call-template name="DisplayPhoneNumber">
<xsl:with-param name="position" select="'1'" />
<xsl:with-param name="phonenumber"
select="sc:fld('phone', .)" />
</xsl:call-template>
Thursday, 21 February 2008
Extract the Month from a DateTime Field in Sitecore
sc:formatdate(sc:fld('MyDateField', .),
'd MMM yyyy @ h:mm')However, extracting just the month as a number without padding is less obvious. Using the format string 'MMM' gives three-letter month names, 'MM' gives months padded with zeros (eg. 02 for Feb), while 'M' curiously gives full month name and date padded with zeros.
A workaround is to use substring-after in conjunction with the format '/M'. Example:
substring-after(sc:formatdate(
sc:fld('MyDateField', .), '/M'), '/')
Friday, 15 February 2008
Get the Path of a Sitecore File Field Given a Media Path
<a href="{sc:fld('Path', sc:item(concat('/sitecore/media library', sc:fld('filefieldname', .)), .))}">Download file</a>
Monday, 11 February 2008
Setting Query String Parameters in Xslt
Here’s a workaround. Let’s say you want to add a parameter called ‘page’.
First, build up the rest of the query string. The following template checks the existence in the query string of parameter names passed to it. You need to know the names of the possible parameters. If they exist, they are written out.
<xsl:template name="SetQueryParameter">
<xsl:param name="name" />
<xsl:if test="sc:qs($name)">
<xsl:text>&</xsl:text>
<xsl:value-of select="$name" />
<xsl:text>=</xsl:text>
<xsl:value-of select="sc:qs($name)" />
</xsl:if>
</xsl:template>
This template would typically be called from within a variable definition, therefore saving the created query string. In the following example, we are checking parameters type and orderby and saving them if they exist so we can add them back in later:
<xsl:variable name="RestOfQueryString">
<xsl:call-template name="SetQueryParameter">
<xsl:with-param name="name">type</xsl:with-param>
</xsl:call-template>
<xsl:call-template name="SetQueryParameter">
<xsl:with-param name="name">orderby</xsl:with-param>
</xsl:call-template>
</xsl:variable>
You are then able to append this query string to your newly-added parameter, which you add using a ‘?’:
<a>
<xsl:attribute name="href">
<xsl:text>?page=10</xsl:text>
<xsl:value-of select="$RestOfQueryString" />
</xsl:attribute>
<xsl:text>Page 10</xsl:text>
</a>
Tuesday, 15 January 2008
Implementing the MVP Pattern in Sitecore XSLT Extension Methods
In the example I use, a “for-each” loop is used to display a list of makes of car.
First, create the view interface, defining the property or properties you want to display in the XSLT. As we are returning an array of values, the XPathNodeIterator return type is used:
{
XPathNodeIterator Cars { get; set; }
}Create an interface defining the method that will get the data or information from store:
{
XPathNodeIterator GetListOfCars();
}In your data access layer (DAL), implement the method that gets the data:
public XPathNodeIterator GetListOfCars()
{var cars = from c in GetMyData()
orderby c.Make
select c;
XDocument xdoc = new XDocument();
XElement xmlTree = new XElement("Cars");
foreach( var car in cars )
{
xmlTree.Add(new XElement("Car",
new XAttribute("Make", car.Make)));
}
xdoc.Add(xmlTree);
return xdoc.CreateNavigator().Select("/Cars/Car");
}Create the presenter class, which will store references to the view and DAL method interfaces, and define the method(s) that will set the value of the property or properties on the view:
public class CarsPresenter
{
private readonly ICarsView _view;
private readonly ICar _icar;
public CarsPresenter( ICarsView view, ICar car )
{
_view = view;
_icar = car;
}
public void SetCarsProperty()
{
_view.Cars = _icar.GetListOfCars();
}
}
Create the extension method that implements the view:
public class CarsView: ICarsView
{public XPathNodeIterator GetListOfCars()
{CarsPresenter cp = new CarsPresenter(this, new CarsDal());
cp.SetCarsProperty ();
return Cars;}
#region IAgreementsView Memberspublic XPathNodeIterator Cars
{get; set;
}
#endregion}
In the web.config file, add an extension element to the xslExtensions element that references the concrete view. Use one such element for each namespace:
<extension mode="on" type="XsltViews.CarsView, XsltViews"
namespace=" http://example.com/xsltviews/cars " />
In your XSLT file, declare the namespace prefix by adding it to the stylesheet element and including the prefix in the exclude-result-prefixes attribute:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:sc="http://www.sitecore.net/sc"
xmlns:dot="http://www.sitecore.net/dot"
xmlns:view="http://example.com/xsltviews/cars"
exclude-result-prefixes="dot sc view">
Finally, you can now call the method from your XSLT:
<xsl:for-each select="view:GetListOfCars()">
<xsl:value-of select="@Make"/>
</xsl:for-each>
Monday, 14 January 2008
Creating Simple Loops in XSLT
I have defined a template that will do the work of the loop. It checks the value of a variable called 'counter' before calling itself. This is the loop condition. Before this test, you can add whatever it is you need the loop to do. In the following example, I print the letters of the alphabet, followed by "... Hello!":
<xsl:template name="DoLoop">
<xsl:param name="counter" />
<xsl:variable name="letter"
select="substring($alphabet, $counter, 1)" />
<!--Body of loop goes here-->
<xsl:value-of select="$letter" />... Hello!
<br/>
<!--End of loop body-->
<xsl:if test="$counter < 26">
<xsl:call-template name="DoLoop">
<xsl:with-param name="counter">
<xsl:value-of select="$counter+1" />
</xsl:with-param>
</xsl:call-template>
</xsl:if>
</xsl:template>
The loop is then initiated by calling it with the desired starting value:
<xsl:call-template name="DoLoop">
<xsl:with-param name="counter">1</xsl:with-param>
</xsl:call-template>
For info, the alphabet variable is simply defined as:
<xsl:variable name="alphabet">
<xsl:text>ABCDEFGHIJKLMNOPQRSTUVWXYZ</xsl:text>
</xsl:variable>
Thursday, 3 January 2008
How to Change String Case in XSLT
<xsl:variable name="lowercasetext" select="translate($inputtext, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')" />
To upper case a string, simply swap the position of the two alphabet literals shown.