这是我的问题:
我的程序将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库轻松实现)?
答案 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));
}
});