Take the 2-minute tour ×
SharePoint Stack Exchange is a question and answer site for SharePoint enthusiasts. It's 100% free, no registration required.

I'm building a custom Xsl to customize the rendering of a ContentByQueryWebPart. This webpart is targeting pictures

In the results, I would like to generate a link to the corresponding dispform.aspx, in order to show the details of the target picture.

How can I generate such link ?

By now, I have created this piece of Xsl to generate the link in my custom ItemStyle.xsl :

<xsl:variable name="DispFormUrl">
    <xsl:value-of
        disable-output-escaping="yes" 
        select="concat($SiteUrl, '/_layouts/listform.aspx?PageType=4&amp;ListId={',@ListId, '}&amp;ID=', @ID)" 
    />
</xsl:variable>

This is working when I work at the root of the site collection. However, this does not works if the results are from another web within the site collection.

How can I correct my xsl to support any location ?

share|improve this question
add comment

2 Answers

up vote 0 down vote accepted

I ended up by creating my Xslt extension functions.

I followed this blog post to create my custom function :

/// <summary>
/// Extend the Xslt transformation by adding new functions
/// </summary>
internal class ContentByQueryWebPartExXsltFunctions
{
    private static readonly Func<KeyValuePair<Guid, Guid>, string> displayFormGetter = FuncExtensions.Memoize(new Func<KeyValuePair<Guid, Guid>, string>((kp) =>
    {
        var site = SPContext.Current.Site;
        using (var web = site.OpenWeb(kp.Key))
        {
            var list = web.Lists[kp.Value];
            return list.DefaultDisplayFormUrl;
        }
    }));

    public string GetDisplayUrl(string webId, string listId, int itemId)
    {
        var webIdGuid = new Guid(webId);
        var listIdGuid = new Guid(listId);
        return displayFormGetter(new KeyValuePair<Guid, Guid>(webIdGuid, listIdGuid)) + "?ID=" + itemId;
    }
}

internal static class FuncExtensions
{
    public static Func<A, R> Memoize<A, R>(this Func<A, R> f)
    {
        var map = new Dictionary<A, R>();
        return a =>
        {
            R value;
            if (map.TryGetValue(a, out value))
                return value;
            value = f(a);
            map.Add(a, value);
            return value;
        };
    }
}

I use Memoization to reduce the opening of multiple SPWeb objects.

Then, I inherited the ContentByQueryWebEx to exploit this functions :

public class ContentByQueryWebPartEx : ContentByQueryWebPart
{
    protected override void ModifyXsltArgumentList(ArgumentClassWrapper argList)
    {
        var functions = new ContentByQueryWebPartExXsltFunctions();

        argList.AddExtensionObject("urn:ContentByQueryWebPartEx", functions);

        base.ModifyXsltArgumentList(argList);
    }

},

Finally, I update my ItemStyle.xsl to register and use this new function :

<xsl:stylesheet
      version="1.0"
      exclude-result-prefixes="x d xsl msxsl cmswrt"
      xmlns:x="http://www.w3.org/2001/XMLSchema"
      xmlns:d="http://schemas.microsoft.com/sharepoint/dsp"
      xmlns:cmswrt="http://schemas.microsoft.com/WebParts/v3/Publishing/runtime"
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      xmlns:msxsl="urn:schemas-microsoft-com:xslt"
      xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime"

      xmlns:cust="urn:ContentByQueryWebPartEx"
    >
    <xsl:template name="MyStyle"
                mode="itemstyle"
                match="Row[@Style='MyStyle']">   

        <xsl:variable name="DispFormUrl">
            <xsl:value-of select="cust:GetDisplayUrl(@WebId,@ListId,@ID)" />
        </xsl:variable>
        <a href="{$DispFormUrl}">Details</a>    

    </xsl:template>

</xsl:stylesheet>
share|improve this answer
    
Thanks Steve! I'm glad you used my blog post as a reference and very nice of you to put the link to it. Thanks again and good work! –  Daniel Hinojo May 9 '13 at 16:51
add comment

In order to provide the link to the picture item instead of picture url, I recommend to modify SafeLinkUrl variable in ItemStyle.xsl that is used for Item Url:

 <xsl:variable name="SafeLinkUrl">
            <!--xsl:call-template name="OuterTemplate.GetSafeLink">
                <xsl:with-param name="UrlColumnName" select="'LinkUrl'"/>
            </xsl:call-template-->
            <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:variable>

CopyUtil.aspx page

CopyUtil.aspx page is an application redirect page intended for redirection to the corresponding item or document.

The following parameters could be passed via URL:

  • Item ID
  • List ID
  • Web ID
  • Site ID
  • Source
  • List item
  • Action
  • InThisWeb
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.