I have the following code:
final TransformerFactory factory = TransformerFactory.newInstance();
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
The second line works fine in modern JDKs (I tried 1.8) with a default TransformerFactory
. But when I add xalan
(version 2.7.2, the most recent one) to classpath, I get the following on that second line:
Exception in thread "main" java.lang.IllegalArgumentException: Not supported: http://javax.xml.XMLConstants/property/accessExternalDTD
at org.apache.xalan.processor.TransformerFactoryImpl.setAttribute(TransformerFactoryImpl.java:571)
at Main.main(Main.java:11)
I guess this is because xalan's TransformerFactory
does not support this attribute. Xalan's implementation gets picked up through ServiceLoader
mechanism: it is specified in services/javax.xml.transform.TransfomerFactory
in xalan jar.
It is possible to override the TransformerFactory
implementation using javax.xml.transform.TransformerFactory
system property or with $JRE/lib/jaxp.properties
file, or pass class name directly in code. But to do it, I must supply a concrete class name. Right now, it is com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl
, but it's a bit scary to hardcode it in a system property, as on JDK upgrade they can easily change the class name, and we will just get a runtime error.
Is there any way to instruct the TransformerFactory.newInstance()
to just ignore that xalan-supplied implementation? Or tell it 'just use the system default'.
P.S. I cannot just remove xalan
from classpath because a bunch of other libraries we use depend on it.
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true)
doesn't prevent Xalan from accessing an external DTD: when I feed an XML with an external DTD link (an http link), Xalan tries to load that DTD and gets aConnectException
. – Khz