如何用XSLT 1.0移除CDATA内XML声明并替换转义字符
XSLT 1.0 实现CDATA内容处理方案
需求回顾
需要完成两个核心操作:
- 移除CDATA块内的XML声明(如
<?xml version="1.0" encoding="UTF-8"?>) - 将CDATA中的
<、>转义字符替换为<、>
示例输入XML
<root> <content><![CDATA[<?xml version="1.0" encoding="UTF-8"?> <note> <to>John</to> <from>Jane</from> </note>]]></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, '<?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> <!-- 模板:递归替换<和>为原生尖括号 --> <xsl:template name="replace-entities"> <xsl:param name="input-text"/> <xsl:choose> <xsl:when test="contains($input-text, '<')"> <xsl:value-of select="substring-before($input-text, '<')"/> <xsl:text><</xsl:text> <xsl:call-template name="replace-entities"> <xsl:with-param name="input-text" select="substring-after($input-text, '<')"/> </xsl:call-template> </xsl:when> <xsl:when test="contains($input-text, '>')"> <xsl:value-of select="substring-before($input-text, '>')"/> <xsl:text>></xsl:text> <xsl:call-template name="replace-entities"> <xsl:with-param name="input-text" select="substring-after($input-text, '>')"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:value-of select="$input-text"/> </xsl:otherwise> </xsl:choose> </xsl:template> </xsl:stylesheet>
关键说明
- 身份转换模板:保证XML中未指定处理的节点、属性完全保留,仅修改目标CDATA内容。
- XML声明移除逻辑:通过
starts-with检测CDATA内容是否以XML声明开头,再用substring-after截取声明之后的文本,兼容带standalone等属性的各类XML声明。 - 转义字符替换:由于XSLT 1.0无原生字符串替换函数,采用递归模板逐个替换
<和>,确保所有匹配的转义字符都被处理。 - CDATA输出控制:使用
disable-output-escaping="yes"确保替换后的<、>不会被再次转义,同时手动包裹CDATA标记保证输出格式正确。
注意事项
- 需根据实际XML结构修改
match="content/text()"中的节点路径,确保匹配到包含CDATA的目标文本节点。 - 确认XSLT处理器支持
disable-output-escaping特性,主流处理器(如Xalan、Saxon)均支持该功能。
内容的提问来源于stack exchange,提问作者Doottu Biju
相关产品推荐
相关产品推荐

