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

如何用XSLT 1.0移除CDATA内XML声明并替换转义字符

XSLT 1.0 实现CDATA内容处理方案

需求回顾

需要完成两个核心操作:

  • 移除CDATA块内的XML声明(如<?xml version="1.0" encoding="UTF-8"?>)
  • 将CDATA中的&lt;、&gt;转义字符替换为<、>

示例输入XML

<root>
  <content><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
&lt;note&gt;
  &lt;to&gt;John&lt;/to&gt;
  &lt;from&gt;Jane&lt;/from&gt;
&lt;/note&gt;]]></content>
</root>

预期输出XML

<root>
  <content><![CDATA[<note>
  <to>John</to>
  <from>Jane</from>
</note>]]></content>
</root>

实现XSLT代码

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <!-- 默认复制所有节点与属性的身份转换模板 -->
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <!-- 处理包含CDATA的目标节点(此处为content节点,需根据实际结构修改) -->
  <xsl:template match="content/text()">
    <!-- 第一步:移除XML声明 -->
    <xsl:variable name="no-declaration">
      <xsl:call-template name="strip-xml-declaration">
        <xsl:with-param name="input-text" select="."/>
      </xsl:call-template>
    </xsl:variable>
    <!-- 第二步:替换转义字符 -->
    <xsl:variable name="unescaped-text">
      <xsl:call-template name="replace-entities">
        <xsl:with-param name="input-text" select="$no-declaration"/>
      </xsl:call-template>
    </xsl:variable>
    <!-- 输出处理后的CDATA内容 -->
    <xsl:text disable-output-escaping="no"><![CDATA[</xsl:text>
    <xsl:value-of select="$unescaped-text" disable-output-escaping="yes"/>
    <xsl:text disable-output-escaping="no">]]></xsl:text>
  </xsl:template>

  <!-- 模板:移除开头的XML声明 -->
  <xsl:template name="strip-xml-declaration">
    <xsl:param name="input-text"/>
    <xsl:choose>
      <xsl:when test="starts-with($input-text, '&lt;?xml')">
        <!-- 截取XML声明结束符(?>)之后的内容 -->
        <xsl:value-of select="substring-after($input-text, '?>')"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$input-text"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <!-- 模板:递归替换&lt;和&gt;为原生尖括号 -->
  <xsl:template name="replace-entities">
    <xsl:param name="input-text"/>
    <xsl:choose>
      <xsl:when test="contains($input-text, '&lt;')">
        <xsl:value-of select="substring-before($input-text, '&lt;')"/>
        <xsl:text><</xsl:text>
        <xsl:call-template name="replace-entities">
          <xsl:with-param name="input-text" select="substring-after($input-text, '&lt;')"/>
        </xsl:call-template>
      </xsl:when>
      <xsl:when test="contains($input-text, '&gt;')">
        <xsl:value-of select="substring-before($input-text, '&gt;')"/>
        <xsl:text>></xsl:text>
        <xsl:call-template name="replace-entities">
          <xsl:with-param name="input-text" select="substring-after($input-text, '&gt;')"/>
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$input-text"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
</xsl:stylesheet>

关键说明

  1. 身份转换模板:保证XML中未指定处理的节点、属性完全保留,仅修改目标CDATA内容。
  2. XML声明移除逻辑:通过starts-with检测CDATA内容是否以XML声明开头,再用substring-after截取声明之后的文本,兼容带standalone等属性的各类XML声明。
  3. 转义字符替换:由于XSLT 1.0无原生字符串替换函数,采用递归模板逐个替换&lt;和&gt;,确保所有匹配的转义字符都被处理。
  4. CDATA输出控制:使用disable-output-escaping="yes"确保替换后的<、>不会被再次转义,同时手动包裹CDATA标记保证输出格式正确。

注意事项

  • 需根据实际XML结构修改match="content/text()"中的节点路径,确保匹配到包含CDATA的目标文本节点。
  • 确认XSLT处理器支持disable-output-escaping特性,主流处理器(如Xalan、Saxon)均支持该功能。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 14:07:46