最近一个处理非常大的XML的程序遭遇了如下的异常:
org.xml.sax.SAXParseException:Parser has reached the entity expansion limit "64,000" set by the Application.
(org.xml.sax.SAXParseException: 分析器已达到由应用程序设置的实体扩展限制“64,000”。)
查了查,原来是在单个xml文件中实体引用超过了默认值64000个。你用dom和sax解析XML都可能会遇到这个问题,这印证了我的猜测,java的dom是用sax来实现的。
解决方法很简单,运行Java的时候,加上参数-DentityExpansionLimit=xxxxx,你也可以在代码中解析XML前,用代码设置这个参数System.setProperty("entityExpansionLimit", "xxxxx");。xxxxx代表设定的单文件实体引用数最大值。
--------
那么这个xxxxx该怎么选择呢?
其实也很简单,选择你认为可能出现的最大值就好了,比你的文件里面的实体数多,自然就没问题了。
--------
那么如果你想知道某个文件里面有多少个实体引用该怎么办呢(放心我肯定不建议你去数)?
对,也很简单,首先我们知道实体引用都是“&"开头“;”结尾,所以我们可以用如下命令来计算:
grep -c "&.*;" yourfile.xml
其实,&在xml里表示为&的形式,所以,一个合法的xml内,有多少&就有多少实体引用,so,上面的命令效率更高的版本是:
grep -c "&" yourfile.xml
--------
为什么会对最大的实体引用数做出限制呢?这点我有些疑惑,难道要为解析实体引用准备缓存空间?但是做出来自动增长的缓存也不是不可能的啊。DentityExpansionLimit参数的问题是,如果要处理无法预期大小的xml文件怎么办?你设置为100万,xml文件里面有200万个实体引用,你有办法么?