【发布时间】:2012-03-10 07:43:21
【问题描述】:
当我将这个 xhtml 文件解析为 xml 时,对这样一个简单的文件进行解析大约需要 2 分钟。我发现如果我删除 doctype 声明,它会立即解析。是什么问题导致该文件需要这么长时间才能解析?
Java 示例
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware( true );
DocumentBuilder bob = dbf.newDocumentBuilder();
Document template = bob.parse( new InputSource( new FileReader( xmlFile ) ) );
XHTML 示例
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ex="http://www.example.com/schema/v1_0_0">
<head><title>Test</title></head>
<body>
<h1>Test</h1>
<p>Hello, World!</p>
<p><ex:test>Text</ex:test></p>
</body>
</html>
谢谢
编辑:解决方案
为了根据提供的有关问题发生原因的信息实际解决问题,我执行了以下基本步骤:
- 已将 DTD 相关文件下载到 src/main/resources 文件夹中
- 创建了一个自定义 EntityResolver 来从类路径中读取这些文件
- 告诉我的 DocumentBuilder 使用我的新 EntityResolver
我在这样做时引用了这个 SO 答案:how to validate XML using java?
新的实体解析器
import java.io.IOException;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
public class LocalXhtmlDtdEntityResolver implements EntityResolver {
/* (non-Javadoc)
* @see org.xml.sax.EntityResolver#resolveEntity(java.lang.String, java.lang.String)
*/
@Override
public InputSource resolveEntity( String publicId, String systemId )
throws SAXException, IOException {
String fileName = systemId.substring( systemId.lastIndexOf( "/" ) + 1 );
return new InputSource(
getClass().getClassLoader().getResourceAsStream( fileName ) );
}
}
如何使用新的EntityResolver:
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware( true );
DocumentBuilder bob = dbf.newDocumentBuilder();
bob.setEntityResolver( new LocalXhtmlDtdEntityResolver() );
Document template = bob.parse( new InputSource( new FileReader( xmlFile ) ) );
【问题讨论】:
-
正如其他人指出的那样,解析器正在尝试从互联网下载资源;你需要自己resolve这些实体。
-
由于某种原因,这个解决方案对我不起作用。所以我刚刚安装了squid并添加了 -Dhttp.proxyHost=localhost -Dhttp.proxyPort=3128