views:

57

answers:

4

I've got a SharePoint problem which I need some help with. I'm creating some custom ItemStyles to format the output of a Content Query Webpart (CQWP) but I need to insert a "view all" button into the output.

View all needs to point to: http://www.site.com/subsite/doclibrary1/Forms/AllItems.aspx

All the individual files in the document library have the link of: http://www.site.com/subsite/doclibrary1/FileName.doc

So what I need is some XSL functions to strip FileName.doc from the end of the string.

I've tried using substring-before($variable, '.') to get rid of the .doc, but I then need to find a way to use substring-after to search for the LAST forward slash in the series and truncate the orphaned filename.

Using @Mads Hansen's post, this is the code which resolved the problem:

Template in ItemStyle.xsl

<xsl:template name="ImpDocs" match="Row[@Style='ImpDocs']" mode="itemstyle">
    <xsl:variable name="SafeLinkUrl">
        <xsl:call-template name="OuterTemplate.GetSafeLink">
            <xsl:with-param name="UrlColumnName" select="'LinkUrl'"/>
        </xsl:call-template>
    </xsl:variable>
    <xsl:variable name="ViewAllLink">
        <xsl:call-template name="OuterTemplate.getCleanURL">
            <xsl:with-param name="path" select="@LinkUrl"/>
        </xsl:call-template>
    </xsl:variable>
    <div class="DocViewAll">
        <a href="{$ViewAllLink}Forms/AllItems.aspx" title="View all">View All</a>
        <!--Any other code you need for your custom ItemStyle here-->
    </div>
</xsl:template>

Template in ContentQueryMain.xsl

<xsl:template name="OuterTemplate.getCleanURL">
    <xsl:param name="path" />
    <xsl:choose>
        <xsl:when test="contains($path,'/')">
            <xsl:value-of select="substring-before($path,'/')" />
            <xsl:text>/</xsl:text>
            <xsl:call-template name="OuterTemplate.getCleanURL">
                <xsl:with-param name="path" select="substring-after($path,'/')" />
            </xsl:call-template>
        </xsl:when>
        <xsl:otherwise />
    </xsl:choose>
</xsl:template>
+1  A: 

Executing this stylesheet produces: http://www.site.com/subsite/doclibrary1/

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">
<xsl:template match="/">

    <xsl:call-template name="getURL">
        <xsl:with-param name="path">http://www.site.com/subsite/doclibrary1/FileName.doc&lt;/xsl:with-param&gt;
    </xsl:call-template>
</xsl:template>

    <xsl:template name="getURL">
        <xsl:param name="path" />
        <xsl:choose>
            <xsl:when test="contains($path,'/')">
                <xsl:value-of select="substring-before($path,'/')" />
                <xsl:text>/</xsl:text>
                <xsl:call-template name="getURL">
                    <xsl:with-param name="path" select="substring-after($path,'/')" />
                </xsl:call-template>
            </xsl:when>
            <xsl:otherwise />
        </xsl:choose>
    </xsl:template>

</xsl:stylesheet>

The getURL template makes a recursive call to itself when there are "/" characters in the string. While there are still "/" characters, it spits out the values before the slash, and then invokes itself. When it reaches the last one, it stops.

Mads Hansen
That's perfect! MOSS is doing a couple of weird things so I'm having trouble actually passing the $path variable into the getURL template, but hopefully I can sort that.
hfidgen
not sure how you are invoking, but `<xsl:with-param>` also has a `@select`, so rather than my example where I put the text value inside the element, you can do this `<xsl:with-param select="$path"/>`
Mads Hansen
perfect - that worked, I'll edit in the code for my solution and thank you!
hfidgen
A: 

If you are using XSLT 2.0 (or more specifically, XPath 2.0), then you should be able to use the replace function, using a regular expression to capture the substring before the last "/": http://www.w3.org/TR/xpath-functions/#func-replace

Unfortunately, "replace" did not exist in XSLT 1.0, so it depends on what XSLT processor you are using as to whether this will work for you.

Erica
A: 

This stylesheet:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
    <xsl:template match="url">
        <xsl:variable name="vReverseUrl">
            <xsl:call-template name="reverse"/>
        </xsl:variable>
        <xsl:call-template name="reverse">
            <xsl:with-param name="pString" 
                            select="substring-after($vReverseUrl,'/')"/>
        </xsl:call-template>
    </xsl:template>
    <xsl:template name="reverse">
        <xsl:param name="pString" select="."/>
        <xsl:if test="$pString">
            <xsl:call-template name="reverse">
                <xsl:with-param name="pString" select="substring($pString,2)"/>
            </xsl:call-template>
            <xsl:value-of select="substring($pString,1,1)"/>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

With this input:

<url>http://www.site.com/subsite/doclibrary1/FileName.doc&lt;/url&gt;

Output:

http://www.site.com/subsite/doclibrary1

One line XPath 2.0:

string-join(tokenize(url,'/')[position()!=last()],'/')
Alejandro
Hey, this is my existing solution to a question from 2-3 days ago!
Dimitre Novatchev
@Dimitre: Well, maybe you are right, I don't know. I think I've already post the XSLT 1.0 solution way back. I was lazy for searching an marking as duplicated...
Alejandro
@Alejandro: Just two days ago I posted this -- I thought you had seen it: http://stackoverflow.com/questions/3862334/how-to-insert-text-with-xslt-v1-0-instead-of-using-an-xslt-v2-0-regex/3865747#3865747
Dimitre Novatchev
@Dimitre: Here is one example http://stackoverflow.com/questions/3521294/using-xslt-and-xmlfor-generating-the-desired-html But I can't find a good "get path question" for marking this as duplicate...
Alejandro
A: 

See my answer to this question and use the same technique (@Alejandro's answer essentially copies this).

Dimitre Novatchev
@Dimitre: I think this http://stackoverflow.com/questions/3116942/doing-file-path-manipulations-in-xslt is more proper, but it's XSLT 2.0 and I don't think it count as duplicate...
Alejandro
@Alejandro: Yes, I know that I have provided this technique in my answers many times.
Dimitre Novatchev
Hiya, Need a XSLT 1.0 solution - so Alejandro's answer has been useful. Wish we could use 2.0, it'd be much simpler!
hfidgen
@hfidgen: Yes, and I gave an XSLT 1.0 solution -- only 2 days before @Alejandro did: here: http://stackoverflow.com/questions/3862334/how-to-insert-text-with-xslt-v1-0-instead-of-using-an-xslt-v2-0-regex/3865747#3865747
Dimitre Novatchev