如何避免SAXBuilder验证文档类型DTD以解决离线时的UnknownHostException问题
如何避免SAXBuilder验证文档类型DTD以解决离线时的UnknownHostException问题
我太懂这个糟心的情况了!明明已经给SAXBuilder传了XMLReaders.NONVALIDATING,结果离线状态下还是会触发UnknownHostException——这是因为NONVALIDATING只是关闭了文档内容的合法性验证,但SAX解析器默认还是会尝试加载外部DTD来处理实体定义,哪怕你不需要验证内容。
给你两个比手动删DTD声明更优雅的解决方案:
方案一:通过EntityResolver拦截DTD加载请求
我们可以给SAXBuilder设置一个自定义的EntityResolver,当解析器尝试加载SVG对应的DTD时,直接返回一个空的输入源,彻底避免联网请求:
try { svgString = svgGraphics.getSVGDocument(); SAXBuilder builder = new SAXBuilder(XMLReaders.NONVALIDATING); // 自定义EntityResolver拦截DTD加载 builder.setEntityResolver((publicId, systemId) -> { // 匹配SVG的DTD地址,直接返回空输入源 if (systemId != null && systemId.contains("w3.org/TR/SVG")) { return new InputSource(new StringReader("")); } // 其他外部资源按默认逻辑处理 return null; }); svgXMLDocument = builder.build(new ByteArrayInputStream(svgString.getBytes())); } catch (IOException | JDOMException e) { // 异常处理逻辑 }
这个方法的好处是精准控制,只拦截SVG的DTD请求,不会影响其他正常的解析逻辑。
方案二:关闭SAX解析器的外部DTD加载特性
还有个更直接的方式:给SAXBuilder设置特定的XML特性,强制关闭非验证模式下的外部DTD加载:
try { svgString = svgGraphics.getSVGDocument(); SAXBuilder builder = new SAXBuilder(XMLReaders.NONVALIDATING); // 关闭非验证模式下加载外部DTD的特性 builder.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); svgXMLDocument = builder.build(new ByteArrayInputStream(svgString.getBytes())); } catch (IOException | JDOMException e) { // 异常处理逻辑 }
这个特性是大部分Java环境默认使用的Apache Xerces解析器提供的,专门用来控制非验证模式下是否加载外部DTD,设置为false之后就彻底不会触发联网请求了。
这两个方案都比手动修改字符串删除DTD声明靠谱,不会因为SVG字符串格式变化(比如DTD声明的写法不一样)导致处理失败,代码也更健壮。
内容来源于stack exchange
相关产品推荐
相关产品推荐

