XSL - 从路径字符串中移除文件名

5
我有一个SharePoint问题需要帮助。我正在创建一些自定义ItemStyles来格式化Content Query Webpart(CQWP)的输出,但我需要在输出中插入“查看全部”按钮。
“查看全部”需要指向: http://www.site.com/subsite/doclibrary1/Forms/AllItems.aspx 文档库中的所有单个文件都具有以下链接: http://www.site.com/subsite/doclibrary1/FileName.doc 所以我需要一些XSL函数来从字符串末尾删除FileName.doc。
我尝试使用substring-before($variable, '.')来摆脱 .doc,但我需要找到一种方法来使用substring-after搜索系列中的最后一个正斜杠并截断孤立的文件名。
使用@Mads Hansen的帖子,这是解决问题的代码:
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>

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>
5个回答

5
执行此样式表会产生以下结果: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>

当字符串中出现“/”字符时,getURL模板会对自身进行递归调用。只要还有“/”字符存在,它就会输出斜杠前面的值,然后再次调用自身。当到达最后一个斜杠时,它将停止。


太好了!MOSS做了一些奇怪的事情,所以我在实际将$path变量传递到getURL模板中遇到了麻烦,但希望我能解决这个问题。 - MrFidge
1
不确定你是如何调用的,但 <xsl:with-param> 也有一个 @select,所以你可以像我的示例一样将文本值放在元素内部,也可以这样做 <xsl:with-param select="$path"/> - Mads Hansen
太好了 - 那个可行,我会编辑我的解决方案的代码并感谢你! - MrFidge

2
给出的解决方案无法处理结尾没有文件名和扩展名的URL(文件夹路径)。
我对上述想法进行了修改,以包括这一点...
   <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> 

顺便问一下,为什么微软还没有支持XSLT 2.0!我看到人们在2007年就抱怨过了-.-'


0

这个样式表:

<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>

使用此输入:

<url>http://www.site.com/subsite/doclibrary1/FileName.doc</url>

输出:

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

一行XPath 2.0:

string-join(tokenize(url,'/')[position()!=last()],'/')

嗨,这是我对2-3天前的一个问题的现有解决方案! - Dimitre Novatchev
@Dimitre:嗯,也许你是对的,我不知道。我想我早就发布了XSLT 1.0解决方案。我懒得搜索并标记为重复... - user357812
@Alejandro: 就在两天前,我发布了这篇文章——我以为你已经看过了它:https://dev59.com/plDTa4cB1Zd3GeqPNe0J#3865747 - Dimitre Novatchev
@Dimitre:这里有一个例子http://stackoverflow.com/questions/3521294/using-xslt-and-xmlfor-generating-the-desired-html 但我找不到一个好的“获取路径问题”来标记它为重复... - user357812

0

如果您正在使用XSLT 2.0(或更具体地说,XPath 2.0),那么您应该能够使用replace函数,使用正则表达式来捕获最后一个“/”之前的子字符串: http://www.w3.org/TR/xpath-functions/#func-replace

不幸的是,“replace”在XSLT 1.0中不存在,因此这取决于您使用的XSLT处理器是否适用于您。


0

请查看我的答案并使用相同的技术(@Alejandro的答案基本上是复制了这个)。


我认为这个https://dev59.com/qE7Sa4cB1Zd3GeqP5aqD更合适,但它是XSLT 2.0,我不认为它算是重复... - user357812
@Alejandro:是的,我知道我在我的回答中多次提供了这种技术。 - Dimitre Novatchev
嗨,需要一个XSLT 1.0的解决方案 - 所以Alejandro的答案很有用。希望我们能使用2.0,那会更简单! - MrFidge
@hfidgen:是的,我提供了一个XSLT 1.0的解决方案——比@Alejandro早了2天:在这里:https://dev59.com/plDTa4cB1Zd3GeqPNe0J#3865747 - Dimitre Novatchev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接