2011-09-22 50 views
0

我目前正在編寫一個使用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 - 有很多潛力)?

回答

1

可以使用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