You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让继承的XSL同时实现格式转换与换行替换?

解决XSL两项功能无法同时生效的问题

问题根源

两个功能互斥,基本是处理顺序冲突或者模板匹配逻辑互相覆盖导致的:要么你先把<2029>/<2028>换成换行,把原本要加格式的文本拆成了多个零散节点,后面的strong/em匹配模板抓不到完整内容;要么先处理了格式替换,把换行标记裹进了标签里,后续替换逻辑识别不出这些标记。

解决思路:分两步链式处理

把两个任务拆成独立的模板,按「先处理格式替换,再处理换行」的顺序执行,确保前一步不破坏后一步的处理条件。

1. 先搞定strong/em格式替换

保留你原来的格式匹配逻辑,但要保证处理时原封不动保留<2029>/<2028>标记——只替换目标文本段,其他内容直接输出。

举个例子(假设你用[strong]/[/strong]标记要加粗的内容):

<!-- 匹配包含加粗标记的文本节点 -->
<xsl:template match="text()[contains(., '[strong]')]">
  <xsl:call-template name="replace-strong">
    <xsl:with-param name="text" select="."/>
  </xsl:call-template>
</xsl:template>

<!-- 递归替换所有加粗标记 -->
<xsl:template name="replace-strong">
  <xsl:param name="text"/>
  <xsl:choose>
    <xsl:when test="contains($text, '[strong]') and contains(substring-after($text, '[strong]'), '[/strong]')">
      <!-- 输出标记前的内容 -->
      <xsl:value-of select="substring-before($text, '[strong]')"/>
      <!-- 用strong标签包裹目标内容 -->
      <strong>
        <xsl:value-of select="substring-before(substring-after($text, '[strong]'), '[/strong]')"/>
      </strong>
      <!-- 递归处理剩余文本 -->
      <xsl:call-template name="replace-strong">
        <xsl:with-param name="text" select="substring-after(substring-after($text, '[strong]'), '[/strong]')"/>
      </xsl:call-template>
    </xsl:when>
    <xsl:otherwise>
      <!-- 没有标记了,直接输出剩余文本 -->
      <xsl:value-of select="$text"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

<!-- 同理写处理em格式的模板 -->

2. 再处理换行符替换

格式替换完成后,专门处理<2029>和<2028>,把它们换成HTML换行<br/>(如果是纯文本就用&#10;)。这里要给这个模板设较低优先级,确保格式替换先执行。

示例模板:

<!-- 优先级设为-1,确保格式替换模板先触发 -->
<xsl:template match="text()" priority="-1">
  <xsl:variable name="processed-text">
    <xsl:call-template name="replace-newlines">
      <xsl:with-param name="text" select="."/>
    </xsl:call-template>
  </xsl:variable>
  <!-- 禁用输出转义,确保<br/>能正常输出 -->
  <xsl:value-of select="$processed-text" disable-output-escaping="yes"/>
</xsl:template>

<!-- 递归替换换行标记 -->
<xsl:template name="replace-newlines">
  <xsl:param name="text"/>
  <xsl:choose>
    <xsl:when test="contains($text, '&lt;2029&gt;')">
      <xsl:value-of select="substring-before($text, '&lt;2029&gt;')"/>
      <br/>
      <xsl:call-template name="replace-newlines">
        <xsl:with-param name="text" select="substring-after($text, '&lt;2029&gt;')"/>
      </xsl:call-template>
    </xsl:when>
    <xsl:when test="contains($text, '&lt;2028&gt;')">
      <xsl:value-of select="substring-before($text, '&lt;2028&gt;')"/>
      <br/>
      <xsl:call-template name="replace-newlines">
        <xsl:with-param name="text" select="substring-after($text, '&lt;2028&gt;')"/>
      </xsl:call-template>
    </xsl:when>
    <xsl:otherwise>
      <xsl:value-of select="$text"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

3. 关键注意点

  • 确保格式替换的模板匹配模式比换行替换的更具体(比如匹配包含[strong]的文本,而换行替换匹配所有文本),或者通过priority属性明确指定执行顺序。
  • 如果你的原XSL有默认的文本节点模板,要删掉或者调整优先级,避免它覆盖这两个处理模板。

效果验证

假设源XML是:

<body>
  <p>[strong]重点内容[/strong]<2029>换行后的内容<2028>[em]强调文本[/em]</p>
</body>

修改后的XSL处理后,会输出:

<p><strong>重点内容</strong><br/>换行后的内容<br/><em>强调文本</em></p>

内容的提问来源于stack exchange,提问作者CMarcera

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 13:48:21