如何在无匹配模板时阻止XSLT生成输出文件?
解决XSLT 2.0无匹配时生成空文件的问题
一、先搞清楚为啥<empty>没输出
你遇到的情况大概率是没匹配到目标节点时,<empty>元素根本没被正确输出,所以处理器只生成了XML声明。常见问题和修复办法:
- 没写根节点模板
默认XSLT会用内置模板遍历节点,但如果没写匹配根节点的模板,没有ns1:FileDesc或ns2:FileRef时,根本触发不了<empty>的输出。得显式写根模板,先判断有没有目标节点,再决定输出内容:
<xsl:template match="/"> <!-- 检查是否存在目标节点 --> <xsl:choose> <xsl:when test="//ns1:FileDesc or //ns2:FileRef"> <!-- 调用匹配目标节点的模板 --> <xsl:apply-templates select="//ns1:FileDesc | //ns2:FileRef"/> </xsl:when> <xsl:otherwise> <!-- 无匹配时输出empty元素 --> <empty/> </xsl:otherwise> </xsl:choose> </xsl:template>
- 默认模板搞事情
如果你的模板只匹配ns1:FileDesc和ns2:FileRef,其他节点的默认模板会输出文本节点;要是没有可输出的节点,就只剩XML声明了。可以禁用默认模板避免这种情况:
<!-- 禁用文本节点默认模板 --> <xsl:template match="text()|@*"/> <!-- 禁用其他元素的默认模板,仅处理子节点 --> <xsl:template match="*"> <xsl:apply-templates/> </xsl:template>
二、完全不生成空文件(得看处理器支持)
要是你要的是没匹配到就不生成任何文件,XSLT 2.0标准本身没提供直接控制是否生成文件的方法,但主流处理器比如Saxon都有解决方案:
- 用Saxon的话这么搞
- 在XSLT里用
xsl:result-document加条件判断,只有存在目标节点时才生成文件:
<xsl:template match="/"> <xsl:if test="//ns1:FileDesc or //ns2:FileRef"> <xsl:result-document href="output.xml"> <xsl:apply-templates select="//ns1:FileDesc | //ns2:FileRef"/> </xsl:result-document> </xsl:if> <!-- 没匹配时不执行result-document,自然不会生成文件 --> </xsl:template>
- 或者调用Saxon的时候,通过命令行参数或API判断转换结果为空就不写入文件。
- 其他处理器(比如Xalan)
可以用代码(Java/.NET均可)调用XSLT处理器,拿到转换后的结果,判断是不是只有XML声明或空内容,再决定要不要写入文件。
三、容易踩的坑总结
- 没显式处理根节点,依赖默认模板导致
<empty>没输出; - 没禁用默认模板,无匹配时处理器仅生成XML声明;
- 搞混了“输出
<empty>元素”和“不生成文件”的需求,得先明确目标再选方案。
内容的提问来源于stack exchange,提问作者vikas mishra
相关产品推荐
相关产品推荐

