1. 程式人生 > >筆記:XML-解析文檔-流機制解析器(SAX、StAX)

筆記:XML-解析文檔-流機制解析器(SAX、StAX)

輸入 tex 字符數 表示 getname 重要 樹形 puts ron

DOM 解析器完整的讀入XML文檔,然後將其轉換成一個樹型的數據結構,對於大多數應用,DOM 都運行很好,但是,如果文檔很大,並且處理算法又非常簡單,可以在運行時解析節點,而不必看到完整的樹形結構,那麽我們應該使用流機制解析器(streaming parser),Java 類庫提供的流解析機制有 SAX 解析器和 StAX 解析器,SAX 解析器是基於事件回調機制,而 StAX解析器提供了解析事件的叠代器。

  1. 使用SAX解析器

    SAX 解析器在解析XML 輸入的組成部分時會報告事件,在使用 SAX 解析器時,需要一個處理器來為不同的解析器事件定義事件動作,ContentHandler 接口定義了若幹個在解析文檔時解析器會調用的回調方法,我們可以使用

    DefaultHandler 類,該類繼承與 ContentHandler 並提供了默認實現,重要的方法如下:

  • startDocument:在文檔開始時調用一次
  • endDocument:在文檔結束時調用一次
  • startElement:在遇到起始標簽時調用,有3個描述元素名的參數,其中qName參數標識標簽限定名,如果命名空間處理特性打開,則 uri 表示的是命名空間,localName 表示的是本地名。
  • endElement:在遇到結束標簽時調用,其參數和 startElement 一致
  • characters:在每當遇到字符數據時調用,如果標簽沒有內容,但有子標簽時,其中的空格會作為字符數據返回

示例代碼如下:

  • 事件處理類

    public class CustomDefaultHandler extends DefaultHandler {

    ????????@Override

    ????????public void startDocument() throws SAXException {

    ????????????????super.startDocument();

    ? ?

    ????????????????System.out.println("call startDocument");

    ????????}

    ? ?

    ????????@Override

    ????????public void endDocument() throws SAXException {

    ????????????????super.endDocument();

    ????????????????System.out.println("call endDocument");

    ????????}

    ? ?

    ????????@Override

    ????????public void characters(char[] ch, int start, int length) throws SAXException {

    ????????????????super.characters(ch, start, length);

    ? ?

    ????????????????String chs = new String(ch, start, length);

    ????????????????System.out.println("characters ch=" + chs + " start=" + start + " length=" + length);

    ????????}

    ? ?

    ????????@Override

    ????????public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {

    ????????????????super.startElement(uri, localName, qName, attributes);

    ? ?

    ????????????????StringBuilder sb = new StringBuilder();

    ????????????????for (int i = 0; i < attributes.getLength(); i++) {

    ????????????????????????sb.append(attributes.getLocalName(i) + "=\"" + attributes.getValue(i) + "\" ");

    ????????????????}

    ? ?

    ????????????????System.out.println("startElement qName=" + qName + " Uri=" + uri + " localName=" + localName + " "

    + sb.toString());

    ????????}

    ? ?

    ????????@Override

    ????????public void endElement(String uri, String localName, String qName) throws SAXException {

    ????????????????super.endElement(uri, localName, qName);

    ? ?

    ????????????????System.out.println("endElement " + qName);

    ????????}

    }

  • 調用類

    try {

    ????????Path xmlPath = Paths.get("E:\\IDEA Workspace\\exampleiostream\\src\\main\\java\\org\\drsoft\\examples\\xml", "appParse.xml");

    ????????InputStream xmlStream = Files.newInputStream(xmlPath, StandardOpenOption.READ);

    ????????SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();

    ????????SAXParser saxParser = saxParserFactory.newSAXParser();

    ????????saxParser.parse(xmlStream, new CustomDefaultHandler());

    } catch (SAXException e) {

    ??????????e.printStackTrace();

    } catch (ParserConfigurationException e) {

    ??????????e.printStackTrace();

    } catch (IOException e) {

    ??????????e.printStackTrace();

    }

  1. 使用StAX解析器

    StAX 解析器時一種拉解析器(pull parser),與安裝事件處理器不同,只需要使用基本的循環來叠代所有事件,示例代碼如下:

    try {

    ??????Path xmlPath = Paths.get("E:\\IDEA Workspace\\exampleiostream\\src\\main\\java\\org\\drsoft\\examples\\xml", "appParse.xml");

    ??????InputStream xmlStream = Files.newInputStream(xmlPath, StandardOpenOption.READ);

    ? ?

    ??????XMLInputFactory factory = XMLInputFactory.newFactory();

    ??????XMLStreamReader parser = factory.createXMLStreamReader(xmlStream);

    ? ?

    ??????while (parser.hasNext()) {

    ??????????????????int event = parser.next();

    ??????????????????switch (event) {

    ??????????????????????????case XMLStreamConstants.START_DOCUMENT:

    ????????????????????????????????????System.out.println("START_DOCUMENT Call");

    ????????????????????????????????????break;

    ? ?

    ??????????????????????????case XMLStreamConstants.END_DOCUMENT:

    ????????????????????????????????????System.out.println("END_DOCUMENT Call");

    ????????????????????????????????????break;

    ? ?

    ??????????????????????????case XMLStreamConstants.START_ELEMENT:

    ????????????????????????????????????StringBuilder sb = new StringBuilder();

    ????????????????????????????????????for (int i = 0; i < parser.getAttributeCount(); i++) {

    ????????????????????????????????????????????sb.append(parser.getAttributeName(i) + "=\"" + parser.getAttributeValue(i) + "\" ");

    ????????????????????????????????????}

    ????????????????????????????????????System.out.println("START_ELEMENT qName=" + parser.getName() + " Uri="

    + parser.getNamespaceURI()?+ " localName=" + parser.getLocalName() + " attribute="

    + sb.toString());

    ????????????????????????????????????break;

    ? ?

    ??????????????????????????case XMLStreamConstants.END_ELEMENT:

    ????????????????????????????????????System.out.println("END_ELEMENT qName=" + parser.getName() + " Uri=" + parser.getNamespaceURI()

    ?????????????????????????????????????????????????????+ " localName=" + parser.getLocalName());

    ????????????????????????????????????break;

    ? ?

    ??????????????????????????case XMLStreamConstants.CHARACTERS:

    ????????????????????????????????????int start = parser.getTextStart();

    ????????????????????????????????????int length = parser.getTextLength();

    ????????????????????????????????????System.out.println("CHARACTERS text=" + new String(parser.getTextCharacters(), start, length));

    ????????????????????????????????????break;

    ????????????????}

    ??????}

    } catch (IOException e) {

    ????????e.printStackTrace();

    } catch (XMLStreamException e) {

    ??????e.printStackTrace();

    }

    ? ?

    ? ?

筆記:XML-解析文檔-流機制解析器(SAX、StAX)