查找并替换为唯一
Posted
技术标签:
【中文标题】查找并替换为唯一【英文标题】:Find and Replace with Unique 【发布时间】:2010-09-07 01:52:54 【问题描述】:我正在对换行符 (

) 执行查找和替换,并使用以下代码将其替换为段落关闭和段落打开标记:
<xsl:template match="/STORIES/STORY">
<component>
<xsl:if test="boolean(ARTICLEBODY)">
<p>
<xsl:call-template name="replace-text">
<xsl:with-param name="text" select="ARTICLEBODY" />
<xsl:with-param name="replace" select="' '" />
<xsl:with-param name="by" select="'</p><p>'" />
</xsl:call-template>
</p>
</xsl:if>
</component>
</xsl:template>
<xsl:template name="replace-text">
<xsl:param name="text"/>
<xsl:param name="replace" />
<xsl:param name="by" />
<xsl:choose>
<xsl:when test="contains($text, $replace)">
<xsl:value-of select="substring-before($text, $replace)"/>
<xsl:value-of select="$by" disable-output-escaping="yes"/>
<xsl:call-template name="replace-text">
<xsl:with-param name="text" select="substring-after($text, $replace)"/>
<xsl:with-param name="replace" select="$replace" />
<xsl:with-param name="by" select="$by" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$text"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
这几乎可以完美运行,除了我真的需要它来删除换行符,因为段落往往被 2 或更多分隔,导致 </p><p></p><p>
。
是否有可能得到它,以便它在每个段落中只替换一次?
【问题讨论】:
【参考方案1】:鉴于您正在调用的 XPath 函数,我不记得在我的 MSXSL 工作中使用过这些函数,看起来您正在使用与 XPath 2 兼容的处理器。
如果是这样,XPath 2 不是有一个将正则表达式作为第二个参数的 replace(string, pattern, replacement) 函数吗?
<xsl:value-of
select="replace(string(.), ' (\s| )*', '</p><p>')" />
提供一些示例 Xml 输入并了解您计划使用的处理器可能会有所帮助。
从您的原始示例看来,重复的段落似乎都只有一个空格前缀。所以像这种轻微的修改可能会减少欺骗。
<xsl:when test="contains($text, $replace)">
<xsl:variable name="prefix" select="substring-before($text, $replace)" />
<xsl:choose>
<xsl:when test="normalize-string($prefix)!=''">
<xsl:value-of select="$prefix"/>
<xsl:value-of select="$by" disable-output-escaping="yes"/>
</xsl:when>
</xsl:choose>
<xsl:call-template name="replace-text">
<xsl:with-param name="text" select="substring-after($text, $replace)"/>
<xsl:with-param name="replace" select="$replace" />
<xsl:with-param name="by" select="$by" />
</xsl:call-template>
【讨论】:
【参考方案2】:试试这个(XSLT 2.0):
<xsl:template match="/STORIES/STORY">
<component>
<xsl:if test="boolean(ARTICLEBODY)">
<xsl:call-template name="insert_paras">
<xsl:with-param name="text" select="ARTICLEBODY/text()"/>
</xsl:call-template>
</xsl:if>
</component>
</xsl:template>
<xsl:template name="insert_paras">
<xsl:param name="text" />
<xsl:variable name="regex">
<xsl:text> ( |\s)*</xsl:text>
</xsl:variable>
<xsl:variable name="tokenized-text" select="tokenize($text, $regex)"/>
<xsl:for-each select="$tokenized-text">
<p>
<xsl:value-of select="."/>
</p>
</xsl:for-each>
</xsl:template>
在 XML 标记中使用文字字符串通常是个坏主意,因为您不能保证结果是平衡的。
【讨论】:
【参考方案3】:disable-output-escaping
本身并不邪恶,但只有少数情况下应该使用它,而这不是其中之一。在 XSLT 中,您使用的是树,而不是标记字符串。这是一个 XSTL 1.0 解决方案:
<xsl:template match="/STORIES/STORY">
<component>
<xsl:if test="ARTICLEBODY">
<xsl:call-template name="wrap-text">
<xsl:with-param name="text" select="ARTICLEBODY"/>
<xsl:with-param name="delimiter" select="' '"/>
<xsl:with-param name="element" select="'p'"/>
</xsl:call-template>
</xsl:if>
</component>
</xsl:template>
<xsl:template name="wrap-text">
<xsl:param name="text"/>
<xsl:param name="delimiter"/>
<xsl:param name="element"/>
<xsl:choose>
<xsl:when test="contains($text, $delimiter)">
<xsl:variable name="t" select="substring-before($text, $delimiter)"/>
<xsl:if test="normalize-space($t)">
<xsl:element name="$element">
<xsl:value-of select="$t"/>
</xsl:element>
</xsl:if>
<xsl:call-template name="wrap-text">
<xsl:with-param name="text" select="substring-after($text, $delimiter)"/>
<xsl:with-param name="delimiter" select="$delimiter"/>
<xsl:with-param name="element" select="$element"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:if test="normalize-space($text)">
<xsl:element name="$element">
<xsl:value-of select="$text"/>
</xsl:element>
</xsl:if>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
【讨论】:
以上是关于查找并替换为唯一的主要内容,如果未能解决你的问题,请参考以下文章
查找并打印总和为 100 的每个唯一组合,并返回 1 到 100 之间数字的所有此类组合的计数 [重复]