XSL - Removing the filename from the path string
Asked Answered
C

5

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>
Crackdown answered 8/10, 2010 at 12:48 Comment(0)
H
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.

Heighttopaper answered 8/10, 2010 at 12:59 Comment(3)
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.Crackdown
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"/>Heighttopaper
perfect - that worked, I'll edit in the code for my solution and thank you!Crackdown
T
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 -.-'

Toast answered 24/9, 2012 at 15:24 Comment(0)
A
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.

Akin answered 8/10, 2010 at 13:19 Comment(0)
P
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()],'/')
Postwar answered 8/10, 2010 at 13:48 Comment(4)
Hey, this is my existing solution to a question from 2-3 days ago!Permanence
@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...Postwar
@Alejandro: Just two days ago I posted this -- I thought you had seen it: #3862834Permanence
@Dimitre: Here is one example #3521794 But I can't find a good "get path question" for marking this as duplicate...Postwar
P
0

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

Permanence answered 8/10, 2010 at 16:10 Comment(4)
I think this #3117442 is more proper, but it's XSLT 2.0 and I don't think it count as duplicate...Postwar
@Alejandro: Yes, I know that I have provided this technique in my answers many times.Permanence
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!Crackdown
@hfidgen: Yes, and I gave an XSLT 1.0 solution -- only 2 days before @Alejandro did: here: #3862834Permanence

© 2022 - 2024 — McMap. All rights reserved.