我正在编写一个用于 XML 文件后处理的 Java 应用程序。 这些 xml 文件来自 Semantic Mediawiki 的 RDF-Export,因此它们具有 rdf/xml 语法。
我的问题如下: 当我读取 xml 文件时,文件中的所有实体都解析为 Doctype 中指定的值。例如在我的 Doctype 中
<!DOCTYPE rdf:RDF[
<!ENTITY wiki 'http://example.org/smartgrid/index.php/Special:URIResolver/'>
..
]>
在根元素中
<rdf:RDF
xmlns:wiki="&wiki;"
..
>
这意味着
<swivt:Subject rdf:about="&wiki;Main_Page">
成为
<swivt:Subject rdf:about="http://example.org/smartgrid/index.php/Special:URIResolver/Main_Page">
我尝试过使用 JDOM 和标准 Java DOM。 我认为这里相关的代码是针对标准 DOM 的:
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setExpandEntityReferences(false);
factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
对于 JDOM
SAXBuilder builder = new SAXBuilder();
builder.setExpandEntities(false); //Retain Entities
builder.setValidation(false);
builder.setFeature("http://xml.org/sax/features/resolve-dtd-uris", false);
但是实体在整个 xml 文档中都被解析了。 我错过了什么吗?经过数小时的搜索,我只找到了“ExpandEntities”命令,但它们似乎不起作用。
非常感谢任何提示:)
最佳答案
我推荐 JDOM FAQ:
http://www.jdom.org/docs/faq.html#a0350
如何阻止 DTD 加载?即使我关闭验证,解析器也会尝试加载 DTD 文件。
即使关闭验证,XML 解析器也会默认加载外部 DTD 文件,以便为外部实体声明解析 DTD。 Xerces 具有关闭此名为 http://apache.org/xml/features/nonvalidating/load-external-dtd
的行为的功能,如果您知道您正在使用 Xerces,则可以设置此功能在生成器上。
builder.setFeature(
"http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
如果您正在使用其他解析器(如 Crimson),最好的办法是设置一个 EntityResolver 来解析 DTD,而无需实际读取单独的文件。
import org.xml.sax.*;
import java.io.*;
public class NoOpEntityResolver implements EntityResolver {
public InputSource resolveEntity(String publicId, String systemId) {
return new InputSource(new StringBufferInputStream(""));
}
}
然后在生成器中...
builder.setEntityResolver(new NoOpEntityResolver());
这种方法有一个缺点。文档中的任何实体都将解析为空字符串,并有效消失。如果您的文档有实体,您需要设置 setExpandEntities(false) 代码并确保 EntityResolver 仅抑制 DocType。
关于java - 在 JDOM/DOM 中禁用 XML 实体解析,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6861233/