Rendering Content Query Web Part results in Table Layout

It is known that OOB Content Query Web Part (CQWP)  renders results using Lists for arranging items as shown below

In ASP.NET WebForms for Web Control DataList there is a possibility to specify layout rendering mode using property RepeatLayout, what if the similar functionality would be available in CQWP?

So, our  goal to extend CQWP, i.e. in addition to List Layout rendering mode, lets implement functionality for rendering Content Query Web Part results in Plain Old Table Layout.
In this approach, we would like to achieve the following options:

  • Possibility to easily arrange results in columns
  • Specify items direction (horizontal or vertical)

Solution Structure

Content Query Web Part Class

using System;
using System.ComponentModel;
using System.Security.Permissions;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using Microsoft.SharePoint.Publishing.WebControls;
using Microsoft.SharePoint.Security;
using Microsoft.SharePoint.WebPartPages;
namespace CQWPWithTableLayout.WebControls
{
[ToolboxItem(false)]
public class CBQTableLayout : ContentByQueryWebPart
{
#region Control Lifecycle
protected override void CreateChildControls()
{
try
{
base.CreateChildControls();
}
catch (Exception ex)
{
throw;
}
}
protected override void ModifyXsltArgumentList(ArgumentClassWrapper argList)
{
argList.AddParameter("RepeatDirection", string.Empty, RepeatDirection);
argList.AddParameter("RepeatColumns", string.Empty, RepeatColumns);
base.ModifyXsltArgumentList(argList);
}
/// <summary>
/// Return the tool panes that configure this <see cref="T:Microsoft.SharePoint.Publishing.WebControls.ContentByQueryWebPart"/> object..
/// </summary>
[SharePointPermission(SecurityAction.Demand, ObjectModel = true)]
public override ToolPart[] GetToolParts()
{
return new ToolPart[3]
{
new ContentByQueryToolPart(),
new WebPartToolPart(),
new CBQTableLayoutToolPart()
};
}
#endregion
#region Properties
[Category("TableLayout")]
[Personalizable(PersonalizationScope.Shared), DefaultValue(3), WebBrowsable(true)]
public int RepeatColumns { get; set; }
[Category("TableLayout")]
[Personalizable(PersonalizationScope.Shared), DefaultValue(RepeatDirection.Horizontal), WebBrowsable(true)]
public RepeatDirection RepeatDirection { get; set; }
#endregion
}
}

Tool Part Class Implementation with the ability to specify Table Layout properties

using System;
using System.Globalization;
using System.Web.UI.WebControls;
namespace CQWPWithTableLayout.WebControls
{
public class CBQTableLayoutToolPart : Microsoft.SharePoint.WebPartPages.ToolPart
{
public CBQTableLayoutToolPart()
{
Init += InitToolPart;
}
private void InitToolPart(object sender, EventArgs e)
{
Title = "Table Layout Settings";
_targetWebPart = ParentToolPane.SelectedWebPart as CBQTableLayout;
if (_targetWebPart == null)
throw new Exception("Wrong web part type error");
}
protected override void CreateChildControls()
{
CreateTableLayoutSection();
PopulateTableLayoutSection();
base.CreateChildControls();
}
public override void ApplyChanges()
{
this.ApplySettingsSectionChanges();
base.ApplyChanges();
}
private void CreateTableLayoutSection()
{
_columnsBox = new TextBox {MaxLength = 2};
_directionBox = new DropDownList();
var mainTable = new Table { CellPadding = 2, CellSpacing = 2 };
mainTable.Style["border-collapse"] = "collapse";
//Repeat Columns
AddRepeatColumnsProperty(mainTable);
//Repeat Direction
AddRepeatDirectionProperty(mainTable);
Controls.Add(mainTable);
}
private void AddRepeatColumnsProperty(Table section)
{
var rowHeader = new TableRow();
var cellHeader = new TableCell { Text = "Repeat Columns" };
rowHeader.Cells.Add(cellHeader);
section.Rows.Add(rowHeader);
var rowItem = new TableRow();
var cellItem = new TableCell();
cellItem.Controls.Add(_columnsBox);
rowItem.Cells.Add(cellItem);
section.Rows.Add(rowItem);
}
private void AddRepeatDirectionProperty(Table section)
{
var rowHeader = new TableRow();
var cellHeader = new TableCell { Text = "Repeat Direction" };
rowHeader.Cells.Add(cellHeader);
section.Rows.Add(rowHeader);
var rowItem = new TableRow();
var cellItem = new TableCell();
cellItem.Controls.Add(_directionBox);
rowItem.Cells.Add(cellItem);
section.Rows.Add(rowItem);
}
private void PopulateTableLayoutSection()
{
_columnsBox.Text = _targetWebPart.RepeatColumns.ToString(CultureInfo.InvariantCulture);
var directions = Enum.GetValues(typeof(RepeatDirection));
_directionBox.DataSource = directions;
_directionBox.DataBind();
_directionBox.Text = _targetWebPart.RepeatDirection.ToString();
}
protected void ApplySettingsSectionChanges()
{
_targetWebPart.RepeatColumns = int.Parse(_columnsBox.Text);
_targetWebPart.RepeatDirection = (RepeatDirection)Enum.Parse(typeof(RepeatDirection), _directionBox.Text);
}
private TextBox _columnsBox;
private DropDownList _directionBox;
private CBQTableLayout _targetWebPart;
}
}

Web Part manifest file

<?xml version="1.0" encoding="utf-8"?>
<webParts>
<webPart xmlns="http://schemas.microsoft.com/WebPart/v3">
<metaData>
<type name="CQWPWithTableLayout.WebControls.CBQTableLayout, CQWPWithTableLayout, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f96554baea0809a2" />
<importErrorMessage>Cannot import this Web Part.</importErrorMessage>
</metaData>
<data>
<properties>
<property name="Title" type="string">Content Query (Plain Old Table Layout)</property>
<property name="Description" type="string">Displays a dynamic view of content from your site.</property>
<property name="ChromeType">TitleOnly</property>
<property name="ChromeState">Normal</property>
<property name="ItemLimit" type="int">15</property>
<property name="SortBy" type="string">{8c06beca-0777-48f7-91c7-6da68bc07b69}</property>
<property name="SortByDirection" type="Microsoft.SharePoint.Publishing.WebControls.ContentByQueryWebPart+SortDirection,Microsoft.SharePoint.Publishing,Version=14.0.0.0,Culture=neutral,PublicKeyToken=71e9bce111e9429c">Desc</property>
<property name="GroupStyle" type="string">DefaultHeader</property>
<property name="ItemStyle" type="string">Default</property>
<property name="ServerTemplate" type="string"></property>
<property name="MainXslLink" type="string" >/Style Library/XSL Style Sheets/ContentQueryMainTableLayout.xsl</property>
<property name="RepeatColumns" type="int">0</property>
<property name="RepeatDirection" type="System.Web.UI.WebControls.RepeatDirection, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">Vertical</property>
</properties>
</data>
</webPart>
</webParts>

Pay attention that we provide custom XSLT for processing of the CQWP, for more details see How to: Customize XSL for the SharePoint Content By Query Web Part.

Main XSLT style sheet for rendering results in Table Layout

<xsl:stylesheet
version="1.0"
exclude-result-prefixes="x xsl cmswrt cbq"
xmlns:x="http://www.w3.org/2001/XMLSchema"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:cmswrt="http://schemas.microsoft.com/WebPart/v3/Publishing/runtime"
xmlns:cbq="urn:schemas-microsoft-com:ContentByQueryWebPart">
<xsl:output method="xml" indent="no" media-type="text/html" omit-xml-declaration="yes"/>
<xsl:param name="cbq_isgrouping" />
<xsl:param name="cbq_columnwidth" />
<xsl:param name="Group" />
<xsl:param name="GroupType" />
<xsl:param name="cbq_iseditmode" />
<xsl:param name="cbq_viewemptytext" />
<xsl:param name="cbq_errortext" />
<xsl:param name="SiteId" />
<xsl:param name="WebUrl" />
<xsl:param name="PageId" />
<xsl:param name="WebPartId" />
<xsl:param name="FeedPageUrl" />
<xsl:param name="FeedEnabled" />
<xsl:param name="SiteUrl" />
<xsl:param name="BlankTitle" />
<xsl:param name="BlankGroup" />
<xsl:param name="UseCopyUtil" />
<xsl:param name="DataColumnTypes" />
<xsl:param name="ClientId" />
<xsl:param name="Source" />
<xsl:param name="RootSiteRef" />
<xsl:param name="CBQPageUrl" />
<xsl:param name="CBQPageUrlQueryStringForFilters" />
<xsl:param name="RepeatDirection" />
<xsl:param name="RepeatColumns" />
<xsl:variable name="BeginTable" select="string('&lt;table class=&quot;dfwp-list&quot;&gt;')" />
<xsl:variable name="EndTable" select="string('&lt;/table&gt;')" />
<xsl:variable name="BeginTableRow" select="string('&lt;tr&gt;')" />
<xsl:variable name="EndTableRow" select="string('&lt;/tr&gt;')" />
<xsl:variable name="BeginTableCell" select="string('&lt;td class=&quot;dfwp-item&quot;&gt;')" />
<xsl:variable name="EndTableCell" select="string('&lt;/td&gt;')" />
<xsl:template match="/">
<xsl:call-template name="OuterTemplate" />
</xsl:template>
<xsl:template name="OuterTemplate">
<xsl:variable name="Rows" select="/dsQueryResponse/Rows/Row" />
<xsl:variable name="RowCount" select="count($Rows)" />
<xsl:variable name="IsEmpty" select="$RowCount = 0" />
<div id="{concat('cbqwp', $ClientId)}" class="cbq-layout-main">
<xsl:if test="$cbq_iseditmode = 'True' and string-length($cbq_errortext) != 0">
<div class="wp-content description">
<xsl:value-of disable-output-escaping="yes" select="$cbq_errortext" />
</div>
</xsl:if>
<xsl:choose>
<xsl:when test="$IsEmpty">
<xsl:call-template name="OuterTemplate.Empty" >
<xsl:with-param name="EditMode" select="$cbq_iseditmode" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="OuterTemplate.Body">
<xsl:with-param name="Rows" select="$Rows" />
<xsl:with-param name="FirstRow" select="1" />
<xsl:with-param name="LastRow" select="$RowCount" />
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</div>
<xsl:if test="$FeedEnabled = 'True' and $PageId != ''">
<div class="cqfeed">
<xsl:variable name="FeedUrl1" select="concat($SiteUrl,$FeedPageUrl,'xsl=1&amp;web=',$WebUrl,'&amp;page=',$PageId,'&amp;wp=',$WebPartId,'&amp;pageurl=',$CBQPageUrl,$CBQPageUrlQueryStringForFilters)" />
<a href="{cmswrt:RegisterFeedUrl( $FeedUrl1, 'application/rss+xml')}">
<img src="\_layouts\images\rss.gif" border="0" alt="{cmswrt:GetPublishingResource('CbqRssAlt')}"/>
</a>
</div>
</xsl:if>
</xsl:template>
<xsl:template name="OuterTemplate.Empty">
<xsl:param name="EditMode" />
<xsl:if test="$EditMode = 'True' and string-length($cbq_errortext) = 0">
<div class="wp-content description">
<xsl:value-of disable-output-escaping="yes" select="$cbq_viewemptytext" />
</div>
</xsl:if>
</xsl:template>
<xsl:template name="OuterTemplate.Body">
<xsl:param name="Rows" />
<xsl:param name="FirstRow" />
<xsl:param name="LastRow" />
<xsl:value-of disable-output-escaping="yes" select="$BeginTable" />
<xsl:choose>
<xsl:when test="$RepeatDirection = 1">
<xsl:call-template name="OuterTemplate.CallVerticalLayoutTemplate">
<xsl:with-param name="Rows" select="$Rows" />
<xsl:with-param name="FirstRow" select="$FirstRow" />
<xsl:with-param name="LastRow" select="$LastRow" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:for-each select="$Rows">
<xsl:variable name="CurPosition" select="position()" />
<xsl:call-template name="OuterTemplate.CallHorizontalLayoutTemplate">
<xsl:with-param name="CurPosition" select="$CurPosition" />
<xsl:with-param name="LastRow" select="$LastRow" />
</xsl:call-template>
</xsl:for-each>
</xsl:otherwise>
</xsl:choose>
<xsl:value-of disable-output-escaping="yes" select="$EndTable" />
</xsl:template>
<xsl:template name="OuterTemplate.CallVerticalContainerTemplate">
<xsl:param name="RowPosition" />
<xsl:param name="RowsCount" />
<xsl:param name="ColsCount" />
<xsl:if test="$RowPosition &lt;= $RowsCount">
<xsl:value-of disable-output-escaping="yes" select="$BeginTableRow" />
<xsl:variable name="CurPosition" select="$RowPosition" />
<xsl:variable name="AllRows" select="/dsQueryResponse/Rows/Row" />
<xsl:for-each select="$AllRows">
<xsl:variable name="ColPosition" select="position()" />
<xsl:choose>
<xsl:when test="$ColPosition != 1 and $ColPosition &lt;= $ColsCount">
<xsl:variable name="CurPositionAbs" select="$CurPosition + $RowsCount * ($ColPosition – 1)" />
<xsl:if test="$CurPositionAbs &lt;= (count($AllRows))">
<xsl:call-template name="OuterTemplate.CallItemTemplate">
<xsl:with-param name="CurPosition" select="$CurPositionAbs" />
</xsl:call-template>
</xsl:if>
</xsl:when>
<xsl:otherwise>
<xsl:if test="$ColPosition &lt;= $ColsCount">
<xsl:call-template name="OuterTemplate.CallItemTemplate">
<xsl:with-param name="CurPosition" select="$RowPosition" />
</xsl:call-template>
</xsl:if>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
<xsl:value-of disable-output-escaping="yes" select="$EndTableRow" />
</xsl:if>
<xsl:if test="$RowPosition &lt;= $RowsCount">
<xsl:call-template name="OuterTemplate.CallVerticalContainerTemplate">
<xsl:with-param name="RowPosition">
<xsl:value-of select="$RowPosition + 1"/>
</xsl:with-param>
<xsl:with-param name="RowsCount">
<xsl:value-of select="$RowsCount"/>
</xsl:with-param>
<xsl:with-param name="ColsCount">
<xsl:value-of select="$ColsCount"/>
</xsl:with-param>
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template name="OuterTemplate.CallHeaderTemplate">
<xsl:apply-templates select="." mode="header">
</xsl:apply-templates>
</xsl:template>
<xsl:template name="OuterTemplate.CallVerticalLayoutTemplate">
<xsl:param name="Rows" />
<xsl:param name="FirstRow" />
<xsl:param name="LastRow" />
<!–Calc Cols & Rows–>
<xsl:choose>
<xsl:when test="$RepeatColumns = 0 or $RepeatColumns = 1">
<xsl:variable name="ColsCount" select="1" />
<xsl:variable name="RowsCount" select="$LastRow" />
<xsl:call-template name="OuterTemplate.CallVerticalContainerTemplate">
<xsl:with-param name="RowPosition" select="1" />
<xsl:with-param name="RowsCount" select="$RowsCount" />
<xsl:with-param name="ColsCount" select="$ColsCount" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:variable name="ColsCount" select="$RepeatColumns" />
<xsl:variable name="RowsCount" select="floor(($LastRow + $RepeatColumns – 1) div $RepeatColumns)" />
<xsl:call-template name="OuterTemplate.CallVerticalContainerTemplate">
<xsl:with-param name="RowPosition" select="1" />
<xsl:with-param name="RowsCount" select="$RowsCount" />
<xsl:with-param name="ColsCount" select="$ColsCount" />
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="OuterTemplate.CallHorizontalLayoutTemplate">
<xsl:param name="CurPosition" />
<xsl:param name="LastRow" />
<xsl:choose>
<xsl:when test="$RepeatColumns = 0">
<xsl:if test="$CurPosition = 1">
<xsl:value-of disable-output-escaping="yes" select="$BeginTableRow" />
</xsl:if>
</xsl:when>
<xsl:otherwise>
<xsl:if test="$CurPosition mod $RepeatColumns = 1">
<xsl:value-of disable-output-escaping="yes" select="$BeginTableRow" />
</xsl:if>
</xsl:otherwise>
</xsl:choose>
<xsl:call-template name="OuterTemplate.CallItemTemplate">
<xsl:with-param name="CurPosition" select="$CurPosition" />
</xsl:call-template>
<xsl:choose>
<xsl:when test="$RepeatColumns = 0">
<xsl:if test="$CurPosition = $LastRow">
<xsl:value-of disable-output-escaping="yes" select="$EndTableRow" />
</xsl:if>
</xsl:when>
<xsl:otherwise>
<xsl:if test="$CurPosition mod $RepeatColumns = 0">
<xsl:value-of disable-output-escaping="yes" select="$EndTableRow" />
</xsl:if>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="OuterTemplate.CallItemTemplateDummy">
<xsl:param name="CurPosition" />
<xsl:value-of disable-output-escaping="yes" select="$BeginTableCell" />
<xsl:value-of disable-output-escaping="yes" select="$CurPosition" />
<xsl:value-of disable-output-escaping="yes" select="$EndTableCell" />
</xsl:template>
<xsl:template name="OuterTemplate.CallItemTemplate">
<xsl:param name="CurPosition" />
<xsl:value-of disable-output-escaping="yes" select="$BeginTableCell" />
<xsl:choose>
<xsl:when test="@Style='NewsRollUpItem'">
<xsl:apply-templates select="." mode="itemstyle">
<xsl:with-param name="EditMode" select="$cbq_iseditmode" />
</xsl:apply-templates>
</xsl:when>
<xsl:when test="@Style='NewsBigItem'">
<xsl:apply-templates select="." mode="itemstyle">
<xsl:with-param name="CurPos" select="$CurPosition" />
</xsl:apply-templates>
</xsl:when>
<xsl:when test="@Style='NewsCategoryItem'">
<xsl:apply-templates select="." mode="itemstyle">
<xsl:with-param name="CurPos" select="$CurPosition" />
</xsl:apply-templates>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="/dsQueryResponse/Rows/Row[position() = $CurPosition]" mode="itemstyle">
</xsl:apply-templates>
<!–<xsl:value-of disable-output-escaping="yes" select="$CurPosition" />–>
</xsl:otherwise>
</xsl:choose>
<xsl:value-of disable-output-escaping="yes" select="$EndTableCell" />
</xsl:template>
<xsl:template name="OuterTemplate.CallFooterTemplate">
</xsl:template>
<xsl:template name="OuterTemplate.GetSafeLink">
<xsl:param name="UrlColumnName"/>
<xsl:if test="$UseCopyUtil = 'True'">
<xsl:value-of select="concat($RootSiteRef,'/_layouts/CopyUtil.aspx?Use=id&amp;Action=dispform&amp;ItemId=',@ID,'&amp;ListId=',@ListId,'&amp;WebId=',@WebId,'&amp;SiteId=',$SiteId,'&amp;Source=',$Source)"/>
</xsl:if>
<xsl:if test="$UseCopyUtil != 'True'">
<xsl:call-template name="OuterTemplate.GetSafeStaticUrl">
<xsl:with-param name="UrlColumnName" select="$UrlColumnName"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template name="OuterTemplate.GetTitle">
<xsl:param name="Title"/>
<xsl:param name="UrlColumnName"/>
<xsl:param name="UseFileName" select="0"/>
<xsl:choose>
<xsl:when test="string-length($Title) != 0 and $UseFileName = 0">
<xsl:value-of select="$Title" />
</xsl:when>
<xsl:when test="$UseCopyUtil = 'True' and $UseFileName = 0">
<xsl:value-of select="$BlankTitle" />
</xsl:when>
<xsl:otherwise>
<xsl:variable name="FileNameWithExtension">
<xsl:call-template name="OuterTemplate.GetPageNameFromUrl">
<xsl:with-param name="UrlColumnName" select="$UrlColumnName" />
</xsl:call-template>
</xsl:variable>
<xsl:choose>
<xsl:when test="$UseFileName = 1">
<xsl:call-template name="OuterTemplate.GetFileNameWithoutExtension">
<xsl:with-param name="input" select="$FileNameWithExtension" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$FileNameWithExtension" />
</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="OuterTemplate.FormatColumnIntoUrl">
<xsl:param name="UrlColumnName"/>
<xsl:variable name="Value" select="@*[name()=$UrlColumnName]"/>
<xsl:if test="contains($DataColumnTypes,concat(';',$UrlColumnName,',URL;'))">
<xsl:call-template name="OuterTemplate.FormatValueIntoUrl">
<xsl:with-param name="Value" select="$Value"/>
</xsl:call-template>
</xsl:if>
<xsl:if test="not(contains($DataColumnTypes,concat(';',$UrlColumnName,',URL;')))">
<xsl:value-of select="$Value"/>
</xsl:if>
</xsl:template>
<xsl:template name="OuterTemplate.FormatValueIntoUrl">
<xsl:param name="Value"/>
<xsl:if test="not(contains($Value,', '))">
<xsl:value-of select="$Value"/>
</xsl:if>
<xsl:if test="contains($Value,', ')">
<xsl:call-template name="OuterTemplate.Replace">
<xsl:with-param name="Value" select="substring-before($Value,', ')"/>
<xsl:with-param name="Search" select="',,'"/>
<xsl:with-param name="Replace" select="','"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template name="OuterTemplate.Replace">
<xsl:param name="Value"/>
<xsl:param name="Search"/>
<xsl:param name="Replace"/>
<xsl:if test="contains($Value,$Search)">
<xsl:value-of select="concat(substring-before($Value,$Search),$Replace)"/>
<xsl:call-template name="OuterTemplate.Replace">
<xsl:with-param name="Value" select="substring-after($Value,$Search)"/>
<xsl:with-param name="Search" select="$Search"/>
<xsl:with-param name="Replace" select="$Replace"/>
</xsl:call-template>
</xsl:if>
<xsl:if test="not(contains($Value,$Search))">
<xsl:value-of select="$Value"/>
</xsl:if>
</xsl:template>
<xsl:template name="OuterTemplate.GetSafeStaticUrl">
<xsl:param name="UrlColumnName"/>
<xsl:variable name="Url">
<xsl:call-template name="OuterTemplate.FormatColumnIntoUrl">
<xsl:with-param name="UrlColumnName" select="$UrlColumnName"/>
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="cmswrt:EnsureIsAllowedProtocol($Url)"/>
</xsl:template>
<xsl:template name="OuterTemplate.GetColumnDataForUnescapedOutput">
<xsl:param name="Name"/>
<xsl:param name="MustBeOfType"/>
<xsl:if test="contains($DataColumnTypes,concat(';',$Name,',',$MustBeOfType,';'))">
<xsl:value-of select="@*[name()=$Name]"/>
</xsl:if>
</xsl:template>
<xsl:template name="OuterTemplate.GetPageNameFromUrl">
<xsl:param name="UrlColumnName"/>
<xsl:variable name="Url">
<xsl:call-template name="OuterTemplate.FormatColumnIntoUrl">
<xsl:with-param name="UrlColumnName" select="$UrlColumnName"/>
</xsl:call-template>
</xsl:variable>
<xsl:call-template name="OuterTemplate.GetPageNameFromUrlRecursive">
<xsl:with-param name="Url" select="$Url"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="OuterTemplate.GetPageNameFromUrlRecursive">
<xsl:param name="Url"/>
<xsl:choose>
<xsl:when test="contains($Url,'/') and substring($Url,string-length($Url)) != '/'">
<xsl:call-template name="OuterTemplate.GetPageNameFromUrlRecursive">
<xsl:with-param name="Url" select="substring-after($Url,'/')"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$Url"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="OuterTemplate.GetGroupName">
<xsl:param name="GroupName"/>
<xsl:param name="GroupType"/>
<xsl:choose>
<xsl:when test="string-length(normalize-space($GroupName)) = 0">
<xsl:value-of select="$BlankGroup"/>
</xsl:when>
<xsl:otherwise>
<xsl:choose>
<xsl:when test="$GroupType='URL'">
<xsl:variable name="Url">
<xsl:call-template name="OuterTemplate.FormatValueIntoUrl">
<xsl:with-param name="Value" select="$GroupName"/>
</xsl:call-template>
</xsl:variable>
<xsl:call-template name="OuterTemplate.GetPageNameFromUrlRecursive">
<xsl:with-param name="Url" select="$Url"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$GroupName" />
</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="OuterTemplate.CallPresenceStatusIconTemplate">
<xsl:if test="string-length(@SipAddress) != 0">
<span class="presence-status-icon">
<img src="/_layouts/images/imnhdr.gif" onload="IMNRC('{@SipAddress}')" ShowOfflinePawn="1" alt="" id="{concat('MWP_pawn_',$ClientId,'_',@ID,'type=sip')}"/>
</span>
</xsl:if>
</xsl:template>
<xsl:template name="OuterTemplate.GetFileNameWithoutExtension">
<xsl:param name="input"/>
<xsl:variable name="extension">
<xsl:value-of select="substring-after($input, '.')"/>
</xsl:variable>
<xsl:choose>
<xsl:when test="contains($extension, '.')">
<xsl:variable name="afterextension">
<xsl:call-template name="OuterTemplate.GetFileNameWithoutExtension">
<xsl:with-param name="input" select="$extension"/>
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="concat(substring-before($input, '.'), $afterextension)"/>
</xsl:when>
<xsl:otherwise>
<xsl:choose>
<xsl:when test="contains($input, '.')">
<xsl:value-of select="substring-before($input, '.')"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$input"/>
</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>

Results

Below is shown Web Part configured  to display results in 4 columns and horizontal mode layout

CBQTableLayoutHorizontal2

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.