A fast way to do sum calculation in XSLT

In general, SharePoint developers avoid XSLT because is limited, this also being the one of the reasons SharePoint 2013 has started to adopt more and more JavaScript. But this doesn’t mean is dead. It is still very powerful being extended with ddwrt functions. I remember one of the challenges in XSLT was to calculate the sum of one column, as starting with SharePoint 2010 numbers output contains commas. It took a while for me also to figure out how I can do this in fast and reliable way, but it turned out was not so complicated as I thought.

<xsl:stylesheet xmlns:x="http://www.w3.org/2001/XMLSchema" xmlns:d="http://schemas.microsoft.com/sharepoint/dsp" version="1.0" exclude-result-prefixes="xsl msxsl ddwrt" xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime" xmlns:asp="http://schemas.microsoft.com/ASPNET/20" xmlns:__designer="http://schemas.microsoft.com/WebParts/v2/DataView/designer" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:SharePoint="Microsoft.SharePoint.WebControls" xmlns:ddwrt2="urn:frontpage:internal">
	<xsl:template match="/">
		<!-- Create a variable TotalAmount and set it to zero -->
		<xsl:value-of select="ddwrt:SetVar('TotalAmount', 0)" />
		<!-- Iterate through the rows and increase TotalAmount with current amount (commas are removed to allow number conversion) -->
		<xsl:for-each select="/dsQueryResponse/Rows/Row">
			<xsl:value-of select="ddwrt:SetVar('TotalAmount', number(translate(@Amount,',','')))" />
		</xsl:for-each>
		<!-- Output the result -->
		<xsl:value-of select="ddwrt:GetVar('TotalAmount')" disable-output-escaping="yes" />
	</xsl:template>
</xsl:stylesheet>

SetVar function is allowing me to create and modify a variable. So with each row included in for-each iteration, the total amount is increased and, at the end of the iteration, calling GetVar function will output the result. This should be fast enough and avoids other operations outside for-each tag. In general, I used at least one for-each declaration per data form web part as the purpose of it is anyhow to show data.

GetVar and SetVar functions are opening a whole word for more complex calculation. Using them I was able to create complicated reports based on SharePoint lists.

Advertisements

Remove hyperlink from lookup field in XSLT list view web part

When you read the title you probably think I will discuss about client side rendering, but I am not. This example is based on SharePoint 2010 an no client side rendering is available for this web part. But you still can do this using classic XSLT and customize only specific items from the view.

I had a list containing time off requests with a lookup column called “Activity” (internal name is the same). By default, this kind of field is render like a hyperlink to the item from lookup list and, by mistake, some users clicked on this link instead of clicking on edit icon.

Timesheet - 0_Start view - Internet Explorer

If you want to remove the hyperlink, open the page with SharePoint Designer and add this code below “XmlDefinition” node.

<Xsl>
<xsl:stylesheet xmlns:x="http://www.w3.org/2001/XMLSchema" xmlns:d="http://schemas.microsoft.com/sharepoint/dsp" version="1.0" exclude-result-prefixes="xsl msxsl ddwrt" xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime" xmlns:asp="http://schemas.microsoft.com/ASPNET/20" xmlns:__designer="http://schemas.microsoft.com/WebParts/v2/DataView/designer" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:SharePoint="Microsoft.SharePoint.WebControls" xmlns:ddwrt2="urn:frontpage:internal" xmlns:o="urn:schemas-microsoft-com:office:office">
<xsl:include href="/_layouts/xsl/main.xsl"/> 
<xsl:include href="/_layouts/xsl/internal.xsl"/>


</xsl:stylesheet>		
</Xsl>

And now we are ready to add customization code for “Activity” field, which contains only a few lines of code, inside “xsl:stylesheet” declaration.

<xsl:template match ="FieldRef[@Name='Activity']"  mode="Lookup_body">
<xsl:param name="thisNode" select="." />
<xsl:param name="activity" select="substring-after($thisNode/@Activity.,'#')" />
<xsl:value-of select="$activity" disable-output-escaping="yes" />
</xsl:template>

Please note that activity parameter doesn’t take the value from “@Activity” attribute of current node. Instead “@Activity.” is used (a dot is added to attribute name). Also, we need to make a “substring-after” operation because the data obtained from the server has this format: “2;#Holiday”.
Timesheet - 1_My time - Internet Explorer

Generate clean HTML in data form web part

A data form web part generated complicated HTML and sometimes creates problem for the designers. When you look into generated HTML you can notice some attributes we don’t want to appear in the markup.

<div style="margin: 0px auto; padding: 0px; width: 800px;" xmlns:ddwrt2="urn:frontpage:internal" xmlns:sharepoint="Microsoft.SharePoint.WebControls" xmlns:__designer="http://schemas.microsoft.com/WebParts/v2/DataView/designer" xmlns:asp="http://schemas.microsoft.com/ASPNET/20" xmlns:d="http://schemas.microsoft.com/sharepoint/dsp" xmlns:x="http://www.w3.org/2001/XMLSchema">

I know you hate them, but I have good news. You can get rid of these very easy. All you need to do is to go to stylesheet declaration and modify value for exclude-result-prefixes like this: ddwrt asp __designer xsl msxsl SharePoint ddwrt2 d x.

<xsl:stylesheet xmlns:x="http://www.w3.org/2001/XMLSchema" xmlns:d="http://schemas.microsoft.com/sharepoint/dsp" version="1.0" exclude-result-prefixes="ddwrt asp __designer xsl msxsl SharePoint ddwrt2 d x" xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime" xmlns:asp="http://schemas.microsoft.com/ASPNET/20" xmlns:__designer="http://schemas.microsoft.com/WebParts/v2/DataView/designer" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:SharePoint="Microsoft.SharePoint.WebControls" xmlns:ddwrt2="urn:frontpage:internal">

Also, you need to be sure you don’t have namespaces declared on template level. Put all namespaces in stylesheet declaration and remove them, if you have, from template declarations.

I did not try yet, but you probably can apply the same thing to XSLT list view web part, if you customize XSLT, as what I described above is XSLT related. But I leave it up to you to try.

Select unique values and create grouping headers in dataformwebpart

Dataformwebpart is probably one the most powerful web parts in SharePoint environment. But one of the biggest problems is it is not very well known by the developers, therefore is considered to be hard to work with. I don’t feel the same and I am still digging into it.

One of the recent challenges working with it was to create from scratch grouping functionality, which is very close related to select distinct values technique in XSLT. Let’s take steps one by one.

First thing, I need to set a parameter to define dynamically grouping criteria. This consists into two changes. One is to bind the parameter in “ParameterBindings” section.

<ParameterBinding  Name="GroupBy" Location="QueryString(GroupBy)" DefaultValue="Title" />

The second step is to let know SPDataSource about parameter and execute select command according to it’s value.

<SharePoint:SPDataSource runat="server" DataSourceMode="List" UseInternalName="true" UseServerDataFormat="false" selectcommand='<![CDATA[<View><Query><GroupBy><FieldRef="{GroupBy}" /></GroupBy></Query></View>]]>'>
<SelectParameters>
<WebPartPages:DataFormParameter Name="ListName" ParameterKey="ListName" PropertyName="ParameterValues" />
<WebPartPages:DataFormParameter Name="GroupBy" ParameterKey="GroupBy" PropertyName="ParameterValues" />
</SelectParameters>
</SharePoint:SPDataSource>

Now, it remained to work with XSLT. This should start with the following code.

<XSL>
<xsl:stylesheet xmlns:x="http://www.w3.org/2001/XMLSchema" xmlns:d="http://schemas.microsoft.com/sharepoint/dsp" version="1.0" exclude-result-prefixes="xsl msxsl ddwrt" xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime" xmlns:asp="http://schemas.microsoft.com/ASPNET/20" xmlns:__designer="http://schemas.microsoft.com/WebParts/v2/DataView/designer" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:SharePoint="Microsoft.SharePoint.WebControls" xmlns:ddwrt2="urn:frontpage:internal">
<xsl:param name="GroupBy" />


</xsl:stylesheet>
</XSL>

Now as our XSLT knows about GroupBy parameter, I need to create grouping headers template and select only distinct values for grouping field.

<xsl:template match="/" xmlns:x="http://www.w3.org/2001/XMLSchema" xmlns:d="http://schemas.microsoft.com/sharepoint/dsp" xmlns:asp="http://schemas.microsoft.com/ASPNET/20" xmlns:__designer="http://schemas.microsoft.com/WebParts/v2/DataView/designer" xmlns:SharePoint="Microsoft.SharePoint.WebControls">

<table>
<thead>
<tr>
<td>Title</td>
</tr>
</thead>
<tbody>
				<xsl:call-template name="GroupHeaders">
				</xsl:call-template>
</tbody>
</table>

</xsl:template>

<xsl:template name="GroupHeaders">
<xsl:for-each select="/dsQueryResponse/Rows/Row[not(@*[name() = $GroupBy] = preceding-sibling::Row/@*[name() = $GroupBy])]">
<xsl:variable name="Attr" select="current()/@*[name() =  $GroupBy]" />
<tr>
<td><xsl:value-of select="$Attr" /></td>
</tr>
</xsl:for-each>
</xsl:template>

Please note how select distinct XSLT technique can adapted to be applied dynamically based on a parameter value. And now is time to call template for showing data for each displayed header.

<xsl:template name="GroupHeaders">
<xsl:for-each select="/dsQueryResponse/Rows/Row[not(@*[name() = $GroupBy] = preceding-sibling::Row/@*[name() = $GroupBy])]">
<xsl:variable name="Attr" select="current()/@*[name() =  $GroupBy]" />
<tr>
<td><xsl:value-of select="$Attr" /></td>
</tr>
<xsl:with-param name="nodeName" select="$GroupBy" />
<xsl:with-param name="nodeValue" select="$Attr" />
</xsl:call-template>
</xsl:for-each>
</xsl:template>


<xsl:template name="RowView">
<xsl:param name="nodeName" />
<xsl:param name="nodeValue" />
<xsl:for-each select="/dsQueryResponse/Rows/Row[@*[name() = $nodeName] =  $nodeValue]">
<tr>
<td><xsl:value-of select="@Title" /></td>
</tr>
</xsl:for-each>
</xsl:template>

I hope this will help you customizing the web part. If you have any question, don’t hesitate to contact me on anvlpopescu@yahoo.com. As always, my code is not perfect, but can give you a start. Happy Codding!

Server rendering in SharePoint (applied to XsltListViewWebPart)

Microsoft is pushing SharePoint development as much as possible on client side by introducing JSLink. But still, I cannot consider old XSLT is dead. So in SharePoint 2013, server rendering is still an available option.

Server Render

To enable server render you just need to tick the Server Render checkbox and provide the path to an XSLT file in XSL link property. Once is enabled, customization will be done on external XSLT file.
There are some articles about how to customize the webpart, but most part of them are a little bit complicated. So I will resume my article on simple customization tasks very likely to be requested in real development.

Change content of a cell

Let’s assume we have field (single line of text), called location, and customer is requiring to display “My location + @Location” instead of location only. This is done pretty straight forward, as you can also note by looking on the code below.

<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet xmlns:x="http://www.w3.org/2001/XMLSchema" xmlns:d="http://schemas.microsoft.com/sharepoint/dsp" version="1.0" exclude-result-prefixes="xsl msxsl ddwrt" xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime" xmlns:asp="http://schemas.microsoft.com/ASPNET/20" xmlns:__designer="http://schemas.microsoft.com/WebParts/v2/DataView/designer" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:SharePoint="Microsoft.SharePoint.WebControls" xmlns:ddwrt2="urn:frontpage:internal" xmlns:o="urn:schemas-microsoft-com:office:office">
<xsl:include href="/_layouts/xsl/main.xsl"/> 
<xsl:include href="/_layouts/xsl/internal.xsl"/> 


<xsl:template name="ShowLocation" ddwrt:dvt_mode="body" match ="FieldRef[@Name='Location']" mode="Text_body" ddwrt:ghost="show">
<xsl:param name="thisNode" select="." />
<xsl:param name="location" select="$thisNode/@Location" />
<xsl:if test="$location != ''">
	<xsl:value-of select="concat('My location is ',$location)" disable-output-escaping="yes" />
</xsl:if>
</xsl:template>
</xsl:stylesheet>

The XSLT is overriding the default content of table cell. Please note it cannot affect TD itself tag or what is outside the TD tag. To change the TD itself, please see the next point.

Change the cell in the view

Sometimes, customer might request to change completely the table cell and its content. A possible reason is to apply a different CSS class on TD tag. Here is how you can do this.

<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet xmlns:x="http://www.w3.org/2001/XMLSchema" xmlns:d="http://schemas.microsoft.com/sharepoint/dsp" version="1.0" exclude-result-prefixes="xsl msxsl ddwrt" xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime" xmlns:asp="http://schemas.microsoft.com/ASPNET/20" xmlns:__designer="http://schemas.microsoft.com/WebParts/v2/DataView/designer" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:SharePoint="Microsoft.SharePoint.WebControls" xmlns:ddwrt2="urn:frontpage:internal" xmlns:o="urn:schemas-microsoft-com:office:office">
<xsl:include href="/_layouts/xsl/main.xsl"/> 
<xsl:include href="/_layouts/xsl/internal.xsl"/> 
<xsl:template name="ShowLocationWithTd" match="FieldRef[@Name='Location']" mode="printTableCellEcbAllowed" ddwrt:dvt_mode="body" ddwrt:ghost="show" xmlns:ddwrt2="urn:frontpage:internal">
<xsl:param name="thisNode" select="." />
<xsl:param name="location" select="$thisNode/@Location" />
<!-- I can change here even the parent tag, if required -->
<td class="mycustomcssclass">
	<xsl:value-of select="$location" disable-output-escaping="yes" />
</td>
</xsl:template>
</xsl:stylesheet>

Change the table row

Let’s go now to a level up, which mean table row. For example, customer required to change the table row into a different tag and display a custom content in it.

<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet xmlns:x="http://www.w3.org/2001/XMLSchema" xmlns:d="http://schemas.microsoft.com/sharepoint/dsp" version="1.0" exclude-result-prefixes="xsl msxsl ddwrt" xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime" xmlns:asp="http://schemas.microsoft.com/ASPNET/20" xmlns:__designer="http://schemas.microsoft.com/WebParts/v2/DataView/designer" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:SharePoint="Microsoft.SharePoint.WebControls" xmlns:ddwrt2="urn:frontpage:internal" xmlns:o="urn:schemas-microsoft-com:office:office">
<xsl:include href="/_layouts/xsl/main.xsl"/> 
<xsl:include href="/_layouts/xsl/internal.xsl"/> 

<xsl:template mode="Item" match="Row" ddwrt:ghost="show">
<xsl:param name="thisNode" select="." />
<xsl:param name="location" select="$thisNode/@Location" />
<!-- TD was changed with DIV -->
<div>
	<xsl:value-of select="$location" disable-output-escaping="yes" />
</div>
</xsl:template>
</xsl:stylesheet>

Change entire view

This is actually my favourite technique because I can easily change the view to look 100% different than default one (quick example in the picture below) and I can write my own and clear XSLT code.

XSLTFull Customization

The code to achieve this is simple and I dare to say is much clear than auto-generated one. The development becomes a simple xsl:for-each iteration, which can be done even by non-experienced developers.

<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet xmlns:x="http://www.w3.org/2001/XMLSchema" xmlns:d="http://schemas.microsoft.com/sharepoint/dsp" version="1.0" exclude-result-prefixes="xsl msxsl ddwrt" xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime" xmlns:asp="http://schemas.microsoft.com/ASPNET/20" xmlns:__designer="http://schemas.microsoft.com/WebParts/v2/DataView/designer" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:SharePoint="Microsoft.SharePoint.WebControls" xmlns:pcm="urn:PageContentManager" xmlns:ddwrt2="urn:frontpage:internal" xmlns:o="urn:schemas-microsoft-com:office:office" ddwrt:ghost="show_all"> 
<xsl:include href="/_layouts/xsl/main.xsl"/> 
<xsl:include href="/_layouts/xsl/internal.xsl"/> 
<xsl:variable name="Fields" select="$XmlDefinition/ViewFields/FieldRef[not(@Explicit='TRUE')]"/>

<xsl:template match="/" ddwrt:ghost="hide">
<div style="display:block; width:100%;">

	<!-- Show the toolbar-->
	<xsl:call-template name="ListViewToolbar"/>
	
	<!-- Displaying the records -->
	<xsl:for-each select="/dsQueryResponse/Rows/Row">
	<xsl:variable name="thisNode" select="." />
	<div style="width:100%; display:block;">
		<xsl:for-each select="$Fields"> 
			<xsl:variable name="FieldName" select="current()/@Name" /> 
			<xsl:variable name="FieldDisplayName" select="current()/@DisplayName" />       
			<div style="display:block; width:100%">
				<strong><xsl:value-of select="$FieldDisplayName" disable-output-escaping="yes" /></strong>: <xsl:value-of select="$thisNode/@*[name() = $FieldName]" disable-output-escaping="yes" />
			</div>
		</xsl:for-each>
	</div>
	<b /><br />
	</xsl:for-each>


</div>
</xsl:template>

</xsl:stylesheet>

I have presented here some concrete and simple examples about how to use XSLT for view customization. I will periodically update this article with new example and additional information, but if you have question, please don’t hesitate to contact me.