我想用Java实现一个程序,以便将DTD文件作为输入 并根据DTD输出XML实例文件。
这意味着我必须在Java中解析和分析DTD文件。 是否有在线可用的API定义分析方法 DTD文件中的结构和元素?
感谢
答案 0 :(得分:3)
解析DTD的一个肮脏的解决方案是滥用Xerces内部。您可以将它作为可接受的东西的起点,因为它已在最近的JRE中可用,源代码可用(使用JDK或来自Apache),并且可以根据您的喜好进行修改(Apache许可证)。请注意,对于具有外部实体等的真实DTD,您必须使用适配器配置XMLDTDLoader(例如setEntityResolver / Feature / Property)。
这是一些试用它的独立代码(对我来说似乎适用于OpenJDK 1.7.0和Oracle JDK 1.8.0):
import org.xml.sax.InputSource;
import com.sun.org.apache.xerces.internal.impl.dtd.DTDGrammar;
import com.sun.org.apache.xerces.internal.impl.dtd.XMLDTDLoader;
import com.sun.org.apache.xerces.internal.util.SAXInputSource;
import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource;
public class So26391485 {
public static void main(String[] args) throws Exception {
// minimal example DTD
StringWriter sw = new StringWriter();
sw.write("<!DOCTYPE html [");
sw.write(" <!ELEMENT html (head, body)>");
sw.write(" <!ELEMENT head (title)> <!ELEMENT title (#PCDATA)>");
sw.write(" <!ELEMENT body (p+)> <!ELEMENT p (#PCDATA)>");
sw.write("]>");
// read DTD
InputStream dtdStream = new ByteArrayInputStream(sw.toString().getBytes());
//InputStream dtdStream = So26391485.class.getResourceAsStream("your.dtd");
Scanner scanner = new Scanner(dtdStream);
String dtdText = scanner.useDelimiter("\\z").next();
scanner.close();
// DIRTY: use Xerces internals to parse the DTD
Pattern dtdPattern = Pattern.compile("^\\s*<!DOCTYPE\\s+(\\S+)\\s*\\[(.*)\\]>\\s*$", Pattern.DOTALL);
Matcher m = dtdPattern.matcher(dtdText);
if (m.matches()) {
String docType = m.group(1);
InputSource is = new InputSource(new StringReader(m.group(2)));
XMLInputSource source = new SAXInputSource(is);
XMLDTDLoader d = new XMLDTDLoader();
DTDGrammar g = (DTDGrammar) d.loadGrammar(source);
g.printElements();
}
}
}
(我不得不砍掉DOCTYPE声明,因为我没有设法让Xerces按原样读取DTD。毕竟XMLDTDLoader不是那样用的......)
答案 1 :(得分:2)
另一个选项是com.sun.xml.dtdparser.DTDParser
,它在JAXB模式编译器中使用。它有一个漂亮的com.sun.xml.dtdparser.DTDParser.parse(InputSource)
方法。我找不到任何例子,但用法可能是:
// Gets the DTD events
DTDEventListener listener = ...;
// Instantiate the parser
DTDParser parser = new DTDParser();
// Set the nandler
parser.setDtdHandler(reader);
// Parse your DTD source
parser. parse(...);
然而,我首先尝试Xerces(参见另一个答案),因为这个DTD解析器似乎已经很老了。我想这甚至是我很久以前就把它复仇了。
通常,基于DTD或XML Schema生成示例XML文件的任务并不容易,据记住,这是2000年左右的博士级resarch主题。我找不到链接但是有一个如果我没有弄错的话,来自IBM的非常好的研究论文。
如今,我不会使用DTD,而是使用XML Schema作为基础。
答案 2 :(得分:1)
遗憾的是,没有用于读取/操作/编写DTD或XML模式的标准API或数据模型。您最好的办法是寻找一个解析器,它为此目的提供自定义API,或者只是将Schema作为XML文档进行操作,并为它构建自己的数据模型。
生成“基于DTD的XML实例文件”通常是一个定义很差的问题。任何给定的DTD都有太多可能的文档,而且没有考虑到您可能希望数据内容在语义上也有意义。您可以使用XML Schema做得更好,但即使这样生成有效文档也只是生成正确文档的冰山一角。编写有助于用户生成格式良好的文档的编辑工具是可能的,但即使这样也很麻烦,因为两个有效文档之间最简单的编辑路径可能是通过无效文档。已经编写了这样做的工具,但它们并没有被广泛使用,因为在大多数情况下,当你需要那么多的帮助时,你想要全力以赴地编写一个完全知道的编辑器。文档语义,包括DTD或Schema无法表达的内容。