如何在Java中解析和分析DTD文件?

时间:2014-10-15 20:26:41

标签: java file parsing dtd

我想用Java实现一个程序,以便将DTD文件作为输入 并根据DTD输出XML实例文件。

这意味着我必须在Java中解析和分析DTD文件。 是否有在线可用的API定义分析方法 DTD文件中的结构和元素?

感谢

3 个答案:

答案 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无法表达的内容。