如何在XSLT输出中保留自定义实体&key;和‐并解决XTSE0020错误
保留XML自定义实体&key;和‐的XSLT解决方案
问题分析
你遇到的XTSE0020错误,根源是<xsl:output-character>的character属性要求必须是单个XML字符,但你在XSLT的DOCTYPE里定义的&key;和‐实体展开后是&key;和‐这类多字符字符串,完全不符合单字符要求,因此触发静态错误。
另外你原XSLT里的实体定义是递归的(<!ENTITY key "&key;">),这种定义本身会导致解析问题,没有实际意义,应直接删除。
可行解决方案
根据你的需求(输出XML保留自定义实体引用),分两种场景处理:
场景1:自定义实体对应单个字符
如果&key;和‐在输入XML的DTD里是单个字符的别名(比如‐对应普通连字符-,&key;对应特殊字符🔑),可以用字符映射实现,步骤如下:
修改字符映射,直接指定单个字符作为匹配目标:
<xsl:character-map name="custom-entities"> <!-- 将连字符替换为‐ --> <xsl:output-character character="-" string="&hyphen;"/> <!-- 将🔑替换为&key; --> <xsl:output-character character="🔑" string="&key;"/> <!-- 保留原有其他字符映射规则 --> <xsl:output-character character="—" string="&mdash;"/> <xsl:output-character character="&" string="&amp;"/> <xsl:output-character character=""" string="&quot;"/> <xsl:output-character character="'" string="&apos;"/> <xsl:output-character character="§" string="&sect;"/> </xsl:character-map>输出XML时必须包含DOCTYPE声明,定义这些实体,否则生成的XML会因实体未定义而不合法:
<xsl:template match="/"> <!DOCTYPE root [ <!ENTITY key "🔑"> <!ENTITY hyphen "-"> ]> <xsl:apply-templates/> </xsl:template>
场景2:自定义实体对应多字符或需原封不动保留引用
如果实体对应多字符,或者你需要直接保留输入里的&key;引用(不管其实际解析值),字符映射无法满足需求,需用模板替换文本节点,结合disable-output-escaping实现:
<xsl:mode on-no-match="shallow-copy"/> <!-- 匹配所有文本节点,替换目标内容为实体引用 --> <xsl:template match="text()"> <!-- 替换&key;对应的解析值为&key;字符串 --> <xsl:variable name="step1" select="replace(., '输入中&key;对应的实际内容', '&key;')"/> <!-- 替换‐对应的解析值为‐字符串 --> <xsl:variable name="final-text" select="replace($step1, '输入中‐对应的实际内容', '&hyphen;')"/> <!-- 禁用转义,直接输出实体引用 --> <xsl:value-of select="$final-text" disable-output-escaping="yes"/> </xsl:template> <!-- 输出DOCTYPE声明,定义实体 --> <xsl:template match="/"> <!DOCTYPE root [ <!ENTITY key "输入中&key;对应的实际内容"> <!ENTITY hyphen "输入中‐对应的实际内容"> ]> <xsl:apply-templates/> </xsl:template>
注意:disable-output-escaping是XSLT的可选特性,部分处理器可能不支持;同时必须确保输出的DOCTYPE与实体定义匹配,否则生成的XML不符合规范。
内容的提问来源于stack exchange,提问作者Rahul
相关产品推荐
相关产品推荐

