如何通过XSL转换输出无效XML?遇select含<报错求解决方案
嘿,我完全懂你的需求——有时候确实会遇到需要生成不严格符合XML规范输出的场景,XSL默认的严格XML规则确实会绊住脚,不过有几个实用的办法可以解决你遇到的报错和问题:
1. 用disable-output-escaping="yes"输出原始特殊字符
XSL会自动转义<、>这类XML特殊字符,这就是你遇到“select语句不得包含<”报错的核心原因。通过给输出文本添加disable-output-escaping="yes"属性,就能让XSL直接输出原始字符而不转义。
举个例子,如果你想输出一个未闭合的<div>标签,可以这么写模板:
<xsl:text disable-output-escaping="yes"><div class="partial-content"></xsl:text>
这里要先把<写成XML实体<,再禁用转义,最终输出就会是真正的<div class="partial-content">而不是转义后的<div...>。
2. 切换输出方法为text绕过XML规则
如果你的输出不需要是完整XML,只是包含部分XML片段,可以直接把XSL的输出模式改成纯文本。在XSL的根节点下添加:
<xsl:output method="text" encoding="UTF-8"/>
切换成text模式后,XSL就不会再以XML规则校验输出内容了,你可以直接写任意文本,包括未闭合的标签:
<xsl:text><div class="raw-output"></xsl:text>
不过要注意,这种模式下所有输出都是纯文本,XSL不会帮你处理任何XML结构相关的逻辑,所有内容都需要你手动控制。
3. 动态生成非标准标签(结合source.xml内容)
如果需要从source.xml里提取元素属性或内容,拼接成未闭合标签,可以用变量+disable-output-escaping的组合,避免在select语句里直接写<。
假设source.xml里有这样的元素:
<source-element target-class="custom-box"/>
你想输出<div class="custom-box">,可以这么写模板:
<xsl:variable name="open-div-tag"> <xsl:text><div class="</xsl:text> <xsl:value-of select="/root/source-element/@target-class"/> <xsl:text>"></xsl:text> </xsl:variable> <xsl:value-of select="$open-div-tag" disable-output-escaping="yes"/>
这样既从source.xml里拿到了动态内容,又避免了select语句中出现<的报错,最终输出未闭合的标签。
额外注意事项
disable-output-escaping不是所有XSL处理器都支持的,主流的比如Saxon、Xalan没问题,但一些轻量处理器可能不兼容,需要提前测试。- 生成非标准XML会导致后续依赖XML解析的工具无法正常处理,除非你的使用场景明确需要这种输出,否则还是优先生成合法XML更稳妥。
内容的提问来源于stack exchange,提问作者Norbert

