티스토리 뷰

자바/Java etc

Java DOM vs SAX parser

주년 2012. 4. 4. 14:54


Java DOM vs SAX parser

[출처] http://blog.naver.com/johnforstar/30072042005

자바에서 XML 파일을 파싱하는 Parser 를 만들기 위해서, 사용할 수 있는 라이브러리들은
다양하다. 그중에서 유명한 것이, DOM 과 SAX 이다.

DOM Parser 는 xml text 의 string들과 stream 들을 parsing 할 때 사용되는 것으로서,
XML 을 parsing 하면서, 트리구조를 만들고 이 트리구조 전체를 메모리 상에 로드 시킨다.

장점은: 사용법이 간단하고, 트리구조 전체를 볼 수 있다는 것.
단점은: 메모리를 많이 먹고, 조금 느리다는 점 이 있다.

더 자세한 정보를 얻고 싶으면 아래의 링크로 가서 살펴보면 도움이 된다.
http://www.w3schools.com/DOM/dom_intro.asp

SAX Parser 는 Simple API for XML Parser 의 약어로, Java API 에서 제공한다.
기본적으로 SAX Parser는 노드들이 들어올때마다 event 가 발생하면서 순차적으로 parsing 을
하게 된다. 그래서 어떤 노드에 무작위 적으로 접근을 하기 위해서는 이 node들을 사용자가 트리구조로 생성한뒤, 메모리에 올려서 사용하여야 한다.

장점은: 순차적으로 파싱을 하기 때문에 속도가 빠르고 메모리를 적게 먹는다.
단점은: 특정 노드를 무작위적으로 접근하는 random access 를 할 수 없다.

본인은 여기서 SAX Parser를 사용하기로 생각을 했다.

기본적으로 SAX Parser를 사용하기 위해서는 아래의 라이브러리들이 필요하다.

import javax.xml.parsers.*;
import org.xml.sax.*;
import org.xml.sax.helpers.*;

그다음 파서가 될 클래스는 DefaultHandler 라는 클래스를 상속 받아야 한다.

다음에는 startElement(...), characters(...), endElement(...) 메소드들의 행동을 구현해야 하고,
SAXParser 의 parse() 메소드를 호출 할 때, 해야 할 일들을 구현해야 한다.

아래의 코드는 SAX Parser를 이용한 간단한 xml file을 파싱하는 예제이다.

import javax.xml.parsers.*;
import org.xml.sax.*;
import org.xml.sax.helpers.*;

import java.io.*;
import java.lang.StringBuffer;

public class SimpleSAXParser extends DefaultHandler {

    private SAXParserFactory parserFact;
    private SAXParser parser;
    private Attributes tagAttributes;

    private String fileName; // xml file name to be parsed
    private String startTagName;
    private String endTagName;
    private String tagData;
    private String [] attrQNames; // attribute's names
    private String [] attrValues; // attribute's values

    private StringBuffer buffer = new StringBuffer();

    public SimpleSAXParser(String fileName)
    {
        super();
        try
        {
            parserFact = SAXParserFactory.newInstance();
            parser = parserFact.newSAXParser();
        }catch(Exception e){}

        this.fileName = fileName;
    }
    // 이 메소드는 태그가 시작될때 이것을 읽으면서 발생하는 이벤트 핸들링 메소드이다.
    // 예: <tag>data</tag> 여기서, 왼쪽에 있는 <tag> 가 읽히면서 발생하는 이벤트
    public void startElement(String uri, String lName, String ele, Attributes attributes)throws SAXException
    {
        startTagName = ele;
        tagAttributes = attributes;

        attrQNames = new String[tagAttributes.getLength()];
        attrValues = new String[tagAttributes.getLength()];

        for(int i = 0; i < tagAttributes.getLength(); i++)
        {
            attrQNames[i] = tagAttributes.getQName(i).trim();
            attrValues[i] = tagAttributes.getValue(i).trim();
        }
        // 여기서 버퍼를 비워줘야, 이전에 버퍼에서 읽었던 것들을 깨끗하게 할 수 있다.
        buffer.setLength(0); // 버퍼 비우기
    }

    // 이 메소드는 태그의 내용을 읽으면서 발생하는 이벤트 핸들링 메소드이다.
    // 예: <tag>data</tag> 여기서, 가운데 있는 data 가 읽히면서 발생하는 이벤트
    public void characters(char[] ch, int start, int len) throws SAXException{
        buffer.append(ch, start, len); // 버퍼에 data 를 집어 넣기.
    }

    // 이 메소드는 태그가 끝날때 이것을 읽으면서 발생하는 이벤트 핸들링 메소드이다.
    // 예: <tag>data</tag> 여기서, 오른쪽에 있는 <tag> 가 읽히면서 발생하는 이벤트
    public void endElement(String uri, String localName, String qName)
    {
        endTagName = qName;
        tagData = buffer.toString().trim(); // end tag 가 오면 버퍼에 있는 내용을 사용
    }

    public void parse(){ // SAXParser 의 parse() method를 호출하여 fileName 이라는 xml 을 파싱
        try {
            parser.parse(fileName, this);
        } catch (SAXException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String [] args){
        if(args.length < 1){
            System.out.println("usage: java InputParser xml_file_name");
            System.exit(0);
        }
        SimpleSAXParser parser = new SimpleSAXParser(args[0]);
        try{
            parser.parse();
            System.out.println("parsing success.");
        } catch(Exception e){
            System.out.println("parsing error.");
            e.printStackTrace();
            System.exit(0);
        }

    }
}