5

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>
MrFidge
  • 2,107
  • 11
  • 40
  • 63

5 Answers5

5

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</xsl:with-param>
    </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
  • 63,927
  • 12
  • 112
  • 147
  • 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. – MrFidge Oct 11 '10 at 09:51
  • 1
    not sure how you are invoking, but `` also has a `@select`, so rather than my example where I put the text value inside the element, you can do this `` – Mads Hansen Oct 11 '10 at 17:33
  • perfect - that worked, I'll edit in the code for my solution and thank you! – MrFidge Oct 12 '10 at 14:03
2

The given solutions are not able to handle url's without filename and extension at the end (Path to folder)

I changed the ideas above to include this aswell...

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

Btw. Why does MS still not support XSLT 2.0!, i saw people complainin bout that back in 2007 -.-'

Sven Mawby
  • 645
  • 6
  • 16
0

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
  • 2,251
  • 16
  • 21
0

This stylesheet:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <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</url>

Output:

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

One line XPath 2.0:

string-join(tokenize(url,'/')[position()!=last()],'/')
  • Hey, this is my existing solution to a question from 2-3 days ago! – Dimitre Novatchev Oct 08 '10 at 16:01
  • @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... –  Oct 08 '10 at 16:10
  • @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 Oct 08 '10 at 16:11
  • @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... –  Oct 08 '10 at 16:34
0

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

Community
  • 1
  • 1
Dimitre Novatchev
  • 240,661
  • 26
  • 293
  • 431
  • 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... –  Oct 08 '10 at 16:48
  • @Alejandro: Yes, I know that I have provided this technique in my answers many times. – Dimitre Novatchev Oct 08 '10 at 17:08
  • 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! – MrFidge Oct 11 '10 at 09:49
  • @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 Oct 11 '10 at 12:29