You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TransformerFactory结合FOP:禁用ACCESS_EXTERNAL_DTD后的大小写匹配问题

问题描述

我正在为一段用FOP库生成PDF文件的代码做XXE防护。原代码基于xalan-2.7.2的org.apache.xalan.processor.TransformerFactoryImpl实现,运行正常:

protected static void transformTo(Result result, Source src, String mimeFormat, String sFileNameXsl)
        throws FOPException {
    try {
        TransformerFactory factory = TransformerFactory.newInstance();

        File myXslFile = new File(sFileNameXsl);
        StreamSource xsltSource = new StreamSource(myXslFile);
        Transformer transformer = factory.newTransformer(xsltSource);
        transformer.setParameter("fop-output-format", mimeFormat);
        transformer.transform(src, result);
    } catch (Exception e) {
        throw new FOPException(e);
    }
}

因为原实现不支持accessExternalDTD属性,我切换到JDK8的com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl来禁用外部DTD和样式表:

TransformerFactory factory = TransformerFactory.newInstance("com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl", ClassLoader.getSystemClassLoader());
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");

属性能正常设置,但运行时出现错误:

FATAL ERROR: Cannot convert data type 'int' in 'node-set'.

排查后发现错误源于XSL中错误使用|操作符匹配大小写不同的元素,例如:

<xsl:variable name="numcolumns" select="count(./html:tr/*)|count(./html:TR/*)"/>

<xsl:if test="ancestor::html:table[1]/@rules = 'cols'|ancestor::html:TABLE[1]/@rules = 'cols'">

移除大写匹配后代码能正常运行,但我需要同时匹配大小写的元素,该怎么实现?

解决方案

问题出在对XSLT中|操作符的误用:|是节点集并集操作符,只能用于节点集之间,不能直接用于数值(比如count的返回值)或布尔值(比如test里的条件表达式)。针对你的场景,应该这样修改:

  1. 处理count统计场景
    将两个节点集合并后再统计数量,而非分别统计后用|连接:
<xsl:variable name="numcolumns" select="count(./html:tr/* | ./html:TR/*)"/>

这里./html:tr/* | ./html:TR/*会合并所有小写tr和大写TR下的子节点,再统一统计总数。

  1. 处理xsl:if条件判断场景
    布尔值之间的逻辑或需要用or操作符,而非节点集并集的|:
<xsl:if test="ancestor::html:table[1]/@rules = 'cols' or ancestor::html:TABLE[1]/@rules = 'cols'">

因为ancestor::html:table[1]/@rules = 'cols'返回的是布尔值,必须用or完成逻辑或判断。

修改后既能保留大小写元素的匹配逻辑,又能兼容JDK内置的Xalan实现,同时完成XXE防护配置。

内容的提问来源于stack exchange,提问作者Nicolas Baumann

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 15:52:44