为何替换XSLT中CDATA转义字符会导致输出异常?
问题描述
我肯定忽略了一些基础内容,还请见谅。
原始XSLT代码
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" omit-xml-declaration="no" indent="yes"/> <xsl:template match="/"> <GenericDataSet> <StatementName> <Header action="INSERT"> <table>XML</table> <access> <XML_DATA><xsl:text disable-output-escaping="yes"><![CDATA[</xsl:text> <xsl:copy-of select="*"/> <xsl:text disable-output-escaping="yes">]]></xsl:text></XML_DATA> </access> </Header> </StatementName> </GenericDataSet> </xsl:template> </xsl:stylesheet>
预期输出(符合预期的结果)
<GenericDataSet> <StatementName> <Header action="INSERT"> <table>XML</table> <access> <XML_DATA><![CDATA[<note> <to>Tove</to> <from>Jani</from> <heading>Reminder</heading> <body>Don't forget me this weekend!</body> </note>]]></XML_DATA> </access> </Header> </StatementName> </GenericDataSet>
修改后的XSLT代码(替换转义字符后)
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" omit-xml-declaration="no" indent="yes"/> <xsl:template match="/"> <GenericDataSet> <StatementName> <Header action="INSERT"> <table>XML</table> <access> <XML_DATA><xsl:text disable-output-escaping="yes"><![CDATA[</xsl:text> <xsl:copy-of select="*"/> <xsl:text disable-output-escaping="yes">]]></xsl:text></XML_DATA> </access> </Header> </StatementName> </GenericDataSet> </xsl:template> </xsl:stylesheet>
异常输出
<GenericDataSet> <StatementName> <Header action="INSERT"> <table>XML</table> <access> <XML_DATA></xsl:text> <xsl:copy-of select="*"/> <xsl:text disable-output-escaping="yes"></XML_DATA> </access> </Header> </StatementName> </GenericDataSet>
请问出现这种情况的原因是什么?我尝试过不同版本的XSLT映射,替换转义字符都会导致结果不同。
原因分析
核心问题在于XSLT本身是XML格式的文档,必须严格遵守XML的语法规则:
- 在XML的文本内容里,
<和>属于特殊字符,不能直接出现,必须转义成<和>,否则XML解析器会把它们误认为是XML标签的起始/结束标记。 - 当你把
<![CDATA[改成<![CDATA[时,XML解析器会把<![CDATA[当成一个新的XML标签的开始,而不是<xsl:text>元素的文本内容。这直接破坏了XSLT文档的结构:解析器会认为<xsl:text>元素在<![CDATA[之前就结束了,后续的]]></xsl:text>也会被拆解成无效的标签片段,最终导致输出混乱。 - 而转义后的
<和>会被XML解析器正确识别为文本内容,在XSLT执行时,通过disable-output-escaping="yes"设置,这些转义字符会被还原成<和>,最终输出正确的CDATA包裹结构。
内容的提问来源于stack exchange,提问作者Integration_Consultant
相关产品推荐
相关产品推荐

