使用SAX获取DOCTYPE详细信息(JDK 7)

时间:2014-04-05 22:38:37

标签: java xml-parsing sax

我正在使用JDK7附带的SAX解析器。我试图抓住DOCTYPE声明,但DefaultHandler中的所有方法似乎都没有被触发。我错过了什么?

import java.io.StringReader;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class Problem {

    public static void main(String[] args) throws Exception {
        String xml = "<!DOCTYPE HTML><html><head></head><body></body></html>";
        SAXParser saxParser = SAXParserFactory.newInstance().newSAXParser();
        InputSource in = new InputSource(new StringReader(xml));
        saxParser.parse(in, new DefaultHandler() {

            @Override
            public void startElement(String uri, String localName, String qName,
                    Attributes attributes) throws SAXException {
                System.out.println("Element: " + qName);
            }
        });;
    }
}

这会产生:

Element: html
Element: head
Element: body

希望它产生:

DocType: HTML
Element: html
Element: head
Element: body

如何获取DocType?


更新:看起来有一个DefaultHandler2类要扩展。我可以将其作为直接替代品吗?

1 个答案:

答案 0 :(得分:2)

使用具有DefaultHander方法的org.xml.sax.ext.DefaultHandler2,而不是startDTD()

  

报告DTD声明的开始(如果有)。这个方法是有意的   报告DOCTYPE声明的开头;如果是文件   没有DOCTYPE声明,不会调用此方法。

     

通过DTDHandler或DeclHandler事件报告的所有声明   必须出现在startDTD和endDTD事件之间。声明是   假设它们属于内部DTD子集,除非它们出现   在startEntity和endEntity事件之间。评论和处理   还应在startDTD之间报告DTD的说明   和endDTD事件,按其原始顺序发生(逻辑);   它们不需要出现在相对于它们的正确位置   但是,DTDHandler或DeclHandler事件。

     

请注意,start / endDTD事件将出现在   来自ContentHandler的start / endDocument事件,在第一个之前   startElement事件。

但是,您还必须为XML Reader设置LexicalHandler。

import java.io.StringReader;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.ext.DefaultHandler2;

public class Problem{

    public static void main(String[] args) throws Exception {
        String xml = "<!DOCTYPE html><hml><img/></hml>";
        SAXParser saxParser = SAXParserFactory.newInstance().newSAXParser();
        InputSource in = new InputSource(new StringReader(xml));

        DefaultHandler2 myHandler = new DefaultHandler2(){
            @Override
            public void startElement(String uri, String localName, String qName,
                    Attributes attributes) throws SAXException {
                System.out.println("Element: " + qName);
            }

            @Override
            public void startDTD(String name,  String publicId,
            String systemId) throws SAXException {
                System.out.println("DocType: " + name);
            }
        };
        saxParser.setProperty("http://xml.org/sax/properties/lexical-handler",
                               myHandler);
        saxParser.parse(in, myHandler);
    }
}