如何在Java中轻松更改XML文档的doctype?

时间:2009-11-17 00:22:51

标签: java xml doctype

这是我的问题:

我的程序将XML文件作为输入。这些文件可能有也可能没有xml声明,doctype声明或实体声明,但它们都符合相同的模式。当我的程序获得一个新文件时,它需要检查它,并确保它有这样的声明:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE my.doctype [
<!ENTITY % entity_file SYSTEM "my.entities.ent">
%entity_file;
]>

如果它有,那很好,我可以保留原样,但如果声明丢失或错误,我需要删除已存在的任何内容并添加正确的声明。

我该怎么做(最好是使用标准的Java 6和/或Apache库轻松实现)?

3 个答案:

答案 0 :(得分:2)

这段代码应该让你开始搞清楚。如果错误,您可能必须创建一个新文档来更改doctype的内容,我不知道修改现有文档的方法。

private Document copyDocument(Document document) {
    DocumentType origDoctype = document.getDoctype();
    DocumentType doctype = documentBuilder
        .getDOMImplementation().createDocumentType(origDoctype.getName(), 
                                                   origDoctype.getPublicId(),
                                                   origDoctype.getSystemId());
    Document copiedDoc = documentBuilder.getDOMImplementation().
        createDocument(null, origDoctype.getName(), doctype);
    // so we already have the top element, and we have to handle the kids.
    Element newDocElement = copiedDoc.getDocumentElement();
    Element oldDocElement = document.getDocumentElement();
    for (Node n = oldDocElement.getFirstChild(); n != null; n = n.getNextSibling()) {
        Node newNode = copiedDoc.importNode(n, true);
        newDocElement.appendChild(newNode);
    }

    return copiedDoc;
}

答案 1 :(得分:0)

如果您可以控制这些文档的形成方式,请尽量避免使用DTD,因为它们会引入不必要的复杂性,并且在表达模式时不够......

答案 2 :(得分:0)

为什么你需要“删除已有的东西并添加正确的声明”?

如果您使用XML文件进行输入,而不是以某种形式将其写回来,那么适当的解决方案是创建EntityResolver

该过程的完整描述是here,但以下代码显示了如何为解析器提供自己的DTD,无论文档说它想要什么:

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
dbf.setValidating(true);
DocumentBuilder db = dbf.newDocumentBuilder();
db.setEntityResolver(new EntityResolver()
{
    public InputSource resolveEntity(String publicId, String systemId)
        throws SAXException, IOException
    {
        return new InputSource(new StringReader(dtd));
    }
});