指定DocumentBuilders用于XML解析的DTD?

时间:2011-09-22 04:03:33

标签: java xml sax xerces docbook

我目前正在编写一个使用Java 1.6的工具,它汇集了许多XML文件。所有文件都验证了DocBook 4.5 DTD(我使用xmllint检查了这一点,并将DocBook 4.5 DTD指定为--dtdvalid参数),但并非所有文件都包含DOCTYPE声明。

我将每个XML文件加载到DOM中以执行所需的操作,如下所示:

private Document fileToDocument( File input ) throws ParserConfigurationException, IOException, SAXException {

    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

    factory.setNamespaceAware(true);
    factory.setIgnoringElementContentWhitespace(false);
    factory.setIgnoringComments(false);
    factory.setValidating(false);
    factory.setExpandEntityReferences(false);

    DocumentBuilder builder = factory.newDocumentBuilder();
    return builder.parse( input );

}

在大多数情况下,这一点非常有效,我可以使用他返回的对象来导航树并执行所需的操作,然后将文档写回。我遇到问题的地方是文件:

  • 不要包含DOCTYPE声明和
  • 包括DTD中定义的实体(例如& mdash; / - )。

在这种情况下,使用消息从builder.parse(...)调用抛出异常:

[Fatal Error] :5:15: The entity "mdash" was referenced, but not declared.

很公平,没有宣布。在这个实例中我理想的做法是将DocumentBuilderFactory设置为始终使用DocBook 4.5 DTD,无论文件中是否指定了一个。

我确实尝试使用DocBook 4.5架构进行验证,但发现这会产生许多与XML无关的错误。似乎模式可能在功能上不等同于DTD,至少对于此版本的DocBook规范而言。

我能想到的另一个选择是读取文件,尝试并检测是否设置了doctype,然后在实际将XML解析到DOM之前设置了一个。

所以,我的问题是,是否有一种更聪明的方式,我没有看到告诉解析器使用特定的DTD或确保解析继续进行尽管实体没有解析(不仅仅是& emdash;示例,但任何实体在XML中 - 有大量的潜力)?

1 个答案:

答案 0 :(得分:1)

可以使用EntityResolver2并实施EntityResolver2.getExternalSubset()帮助吗?

  

...此方法也可用于没有DOCTYPE声明的文档。遇到根元素但未看到DOCTYPE声明时,将调用此方法。如果它返回外部子集的值,则将该根元素声明为根元素,从而产生在文档的序言末尾拼接DOCTYPE声明的效果,否则该元素无效。 ...