用递归方式替换字符串

时间:2011-11-10 09:17:58

标签: xslt replace xslt-2.0

我正在尝试修改字符串,如:
Some {words} should be {bold} ...
对于像 Some <b>words</b> should be <b>bold</b> ...

但是,我的实现忘记了所有<b>元素,但最后一个元素:
Some words should be <b>bold</b> ...

我认为, substring-before()会删除已插入的<b>元素。
这是我的代码:

<xsl:template name="replace">
  <xsl:param name="input"/>

  <xsl:variable name="before" select="substring-before( $input, '{' )" />
  <xsl:variable name="after" select="substring-after( $input, '}' )" />
  <xsl:variable name="replace" select="substring-after( substring-before( $input, '}' ), '${' )" />

  <xsl:choose>
    <xsl:when test="$replace">
      <xsl:call-template name="replace">
        <xsl:with-param name="input">
          <xsl:value-of select="$before" />
          <xsl:element name="b">
            <xsl:value-of select="$replace" />
          </xsl:element>
          <xsl:value-of select="$after" />
        </xsl:with-param>
      </xsl:call-template>
    </xsl:when>
    <xsl:otherwise>
      <xsl:copy-of select="$input" />
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

有什么想法吗?谢谢你的帮助。

2 个答案:

答案 0 :(得分:1)

由于您已将问题标记为XSLT 2.0,我强烈建议您使用analyze-string,即

<text>Some {words} should be {bold} ...</text>

和样式表

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="2.0">

  <xsl:template match="text">
    <xsl:analyze-string select="." regex="\{{(.*?)\}}">
      <xsl:matching-substring>
        <b>
          <xsl:value-of select="regex-group(1)"/>
        </b>
      </xsl:matching-substring>
      <xsl:non-matching-substring>
        <xsl:value-of select="."/>
      </xsl:non-matching-substring>
    </xsl:analyze-string>
  </xsl:template>

</xsl:stylesheet>

输出

Some <b>words</b> should be <b>bold</b> ...

答案 1 :(得分:0)

我自己找到了答案......

仅将剩余的字符串作为参数传递给递归调用:

<xsl:template name="replace">
  <xsl:param name="input"/>

  <xsl:variable name="before" select="substring-before( $input, '{' )" />
  <xsl:variable name="after" select="substring-after( $input, '}' )" />
  <xsl:variable name="replace" select="substring-after( substring-before( $input, '}' ), '${' )" />

  <xsl:choose>
    <xsl:when test="$replace">

      <!-- moved outside the recursive call -->
      <xsl:value-of select="$before" />
      <xsl:element name="b">
        <xsl:value-of select="$replace" />
      </xsl:element>

      <xsl:call-template name="replace">
        <xsl:with-param name="input">
          <xsl:value-of select="$after" />
        </xsl:with-param>
      </xsl:call-template>
    </xsl:when>
    <xsl:otherwise>
      <xsl:copy-of select="$input" />
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

所以 substring-before()函数不是问题......