【问题标题】:How do I easily change a XML document's doctype in Java?如何在 Java 中轻松更改 XML 文档的文档类型?
【发布时间】:2009-11-17 00:22:50
【问题描述】:

这是我的问题:

我的程序正在获取 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 库很容易)?

【问题讨论】:

    标签: java xml doctype


    【解决方案1】:

    这段代码应该让您开始弄清楚它。如果错误,您可能需要创建一个新文档来更改文档类型的内容,我不知道如何修改现有文档。

    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;
    }
    

    【讨论】:

    • 这也是使用 Java 将现有 XML 文档中的 DocumentType 复制到新 XML 文档中的一个很好的起点。
    【解决方案2】:

    为什么需要“删除已经存在的内容并添加正确的声明”?

    如果您使用 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));
        }
    });
    

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        猜你喜欢
        • 2010-09-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-08-27
        • 2015-08-20
        相关资源
        最近更新 更多