XSLT如何多次使用substring-after与concat处理单个字符串
解决RTF字符串中批量移除图片的XSLT方案
你现在的代码只能处理单个图片,遇到多个图片就会遗漏——这是因为substring-before和substring-after只会匹配第一个出现的标记。要处理任意数量的图片,在XSLT里最常用的方法是递归模板(适配XSLT 1.0),如果是XSLT 2.0+也可以用内置的替换函数简化实现,下面分别给出两种方案:
方案1:XSLT 1.0 递归模板实现
首先定义一个递归模板,用来反复扫描并移除所有RTF图片块:
<xsl:template name="remove-rtf-images"> <xsl:param name="text" select="''"/> <xsl:choose> <!-- 检查当前文本是否包含图片起始标记 --> <xsl:when test="contains($text, '{\result{\pict{\*\picprop}')"> <!-- 保留图片之前的内容,然后递归处理图片结束标记之后的剩余文本 --> <xsl:value-of select="substring-before($text, '{\result{\pict{\*\picprop}')"/> <xsl:call-template name="remove-rtf-images"> <xsl:with-param name="text" select="substring-after($text, '}}}')"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <!-- 没有剩余图片,返回最终文本 --> <xsl:value-of select="$text"/> </xsl:otherwise> </xsl:choose> </xsl:template>
然后修改你原有的代码,调用这个模板来处理RTF文本:
<xsl:variable name="storyFormattedText" select="//STORY_TEXT_RTF"/> <xsl:variable name="textWithoutImages"> <xsl:call-template name="remove-rtf-images"> <xsl:with-param name="text" select="$storyFormattedText"/> </xsl:call-template> </xsl:variable> <xsl:call-template name="create_field"> <xsl:with-param name="field_id">15</xsl:with-param> <xsl:with-param name="field_type">1</xsl:with-param> <xsl:with-param name="field_name">Formatted Text ohne Bilder</xsl:with-param> <xsl:with-param name="is_empty">no</xsl:with-param> <xsl:with-param name="value" select="$textWithoutImages"/> </xsl:call-template>
逻辑说明
这个模板会循环执行:每次找到第一个图片块,截取它之前的内容,然后把图片块结束(}}})之后的文本再次传入模板,直到文本中再也找不到图片标记为止,这样就能一次性移除所有图片。
方案2:XSLT 2.0+ 内置replace函数简化实现
如果你使用的是XSLT 2.0或更高版本,可以直接用内置的replace函数结合正则表达式批量替换,代码更简洁:
<xsl:variable name="storyFormattedText" select="//STORY_TEXT_RTF"/> <xsl:variable name="textWithoutImages" select="replace( $storyFormattedText, '\{\result\{\pict\{\*\picprop\}(.*?)\}\}\}', '', 's' )"/> <xsl:call-template name="create_field"> <xsl:with-param name="field_id">15</xsl:with-param> <xsl:with-param name="field_type">1</xsl:with-param> <xsl:with-param name="field_name">Formatted Text ohne Bilder</xsl:with-param> <xsl:with-param name="is_empty">no</xsl:with-param> <xsl:with-param name="value" select="$textWithoutImages"/> </xsl:call-template>
正则说明
\{\result\{\pict\{\*\picprop\}:转义匹配图片的起始标记(因为{和*是正则特殊字符,需要转义)(.*?):非贪婪匹配图片块的内容,确保不会误匹配多个图片块\}\}\}:匹配图片块的结束标记's':开启单行模式,让.可以匹配换行符(处理RTF图片块跨多行的情况)
这样不管你的RTF里有0个还是N个图片,都能一次性处理干净。
内容的提问来源于stack exchange,提问作者David Karlito
相关产品推荐
相关产品推荐

