指定DocumentBuilders用于XML解析的DTD?

问题描述:

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

我每个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规范来说。

我能想到的另一个选项是读取文件,尝试并检测是否设置了文档类型,然后在实际将XML解析到DOM之前找到没有文件的情况下设置一个。

所以,我的问题是,有没有我还没有看到告诉解析器使用特定的DTD或保证解析收益尽管实体未解决(不只是与emdash一个更聪明的方式,例如,但在任何实体XML - 有很多潜力)?

可以使用EntityResolver2并执行EntityResolver2.getExternalSubset()帮助吗?

... This method can also be used with documents that have no DOCTYPE declaration. When the root element is encountered, but no DOCTYPE declaration has been seen, this method is invoked. If it returns a value for the external subset, that root element is declared to be the root element, giving the effect of splicing a DOCTYPE declaration at the end the prolog of a document that could not otherwise be valid. ...

+0

谢谢,我不知道EntityResolver2接口(只有EntityResolver)。一旦我重载了建议的方法,并为其他人提供了默认处理,我现在遇到以下错误: [致命错误] docbookx.dtd:101:9:递归实体引用“%dbnotn”。 (参考路径:%dbnotn - >%dbnotn - >%dbnotn) 基于此,似乎DTD现在至少已被应用,但有其他问题:)。 – xsgordon