Site Search :
Standard Enterprise XML Methodology Pattern Setting Tunning Other
Article Contributors
GuestBook
Javapattern Maven
XSourceGen Dev
JetSpeed Test
JLook Image
jLook Family Site


About SAX & SAX programming with Java
 
파서가 대체 무엇이며, SAX(Simple API for XML)가 도대체 무엇인지 알아보고, JAXP와 Xerces를 이용한 SAX1.0, 2.0프로그래밍은 어떻게 하는지 알아보도록 하자. ( 2003/03/12 ) 385
Written by ienvyou - 최지웅
1 of 1
 

 XML의 기본개요에 대한 아티클을 읽어보았다면 이제 Simpe API form XML인 SAX의 개용와
 프로그래밍 방법에 대하여 알아보도록 하자.

 SAX가 어떤 것이다, 어떻게 작동이 된다라는 것을 알고 있는 당신이라면 과감히 다른 아티클로
 떠나라~~

 자, 그럼 SAX의 기본개요와 간단한 프로그래밍 방법에 대하여 알아보도록 하자.

 ▶ About SAX

    - Simple API for XML Parsing
    - 기존의 event기반 파서의 문제
    - 공통API의 필요성 대두
    - 1998년 5월 XML-DEV에 의한 SAX1.0발표
    - Namespace 추가에 따른 SAX API수정
    - 2000년 5월 SAX2.0발표

기존의 XML을 파싱하기 위한 도구들이 많아지면서 서로 다른 다양한 파서들을 이용하여 개발하려는 
개발자들의 어려움이 증대되는 문제점을 안고 있었는데, 이러한 여러 파서들이 공존하는 
가운데에서 공통의 API가 필요하다는 인식에서 XML-DEV 메일링 리스트의 개발자들이 모여
1998년 5월 SAX1.0을 발표한다.

XML 스펙에 이름충돌로 인한 namespace(이전 아티클에서 설명)의 기능이 추가되면서 기존의 
SAX가 이러한 namespace를 지원할 수 있도록 2000년 5월 SAX2.0을 새로이 발표 한층 더 진보시키게 된다

이러한 SAX2.0은 SAX1.0이 갖지 못했던 namespace와 skippend entity에 대한 지원을 이루게 하였고
기존의 자바측면에서 SAX1.0을 SAX2.0처럼 사용하기 위한 XMLReaderAdapter 클래스와 SAX2.0을 SAX1.0의 
파서처럼 작동시키기 위한 ParseAdapter클래스가 존재하여 이들 1.0과 2.0의 차이에서 오는 
문제점들을 해결해내고 있는 특징을 가지고 있다.

 ▶ 도대체 파서란 무엇을 말하는가

단어만 나열한다고 해서 컴퓨터가 그것을 문장으로 인식하는 것이 아니다. 문법에 맞게 구성되고
또한 단어간의 유기적인 관계가 성립해야함 비로소 의미를 가진 문장이 되는 것이다. 
또한 의미를 갖고 있다는 것보다 중요한 것은 이것을 컴퓨터에게 이해시키는 일이다. 
아무리 좋은 의미를 가진 문장이라도 우리에게는 궁극적으로 컴퓨터가 이해하지 못하면 
아무 소용이 없는 것이다. 

컴퓨터 입장에서 조금 더 이야기하자면 

    - 입력된 텍스트를 어휘 분석 및 구문 분석해 주는 프로그램 
    - 입력된 문장이 문법에 맞는가 여부를 결정해준다. 
    - 문법에 맞는 경우 다른 추가 기능을 할 수도 있다. (파스 트리 생성, 계산, 검색 등등) 

등의 일을 처리하여 사용할 수 있게끔 만들어주는 프로그램이라 보면 된다.

 ▶ SAX의 특징

SAX는 철저한 이벤트 기반 인터페이스이다. 객체 기반 인터페이스인 DOM(Document Object Model)이 
문서의 모든 정보 노드를 메모리상에 저장해야 하므로 많은 메모리 용량의 소모와 이로 인한 
수행 속도가 다소 저하될 수 있는 반면, SAX는 파서가 문서를 파싱하는 동안에 발생하는 이벤트에 
대해서만 반응하고 이를 따로 메모리에 저장하지 않으므로 빠른 수행속도를 가진다. 

그러나 문서정보에 대한 이벤트 발생이 지나가면 이에 대한 정보를 저장하지 않으므로 응용프로그램에서 
처리해야 할 부분이 상대적으로 DOM 보다 복잡해 질 수 있다는 단점이 있다. 
이러한 점 때문에 DOM과 SAX는 그 응용분야가 구분되고 있다.
SAX는 문서의 내용을 생성,수정 하는 응용프로그램에서는 잘 쓰이지 않으며 주로 대용량의 
문서 정보를 빠른 시간 안에 읽어 들이는 작업에 주로 이용되고 있다.

객체 기반 인터페이스와 이벤트 기반 인터페이스의 커다란 차이점은 이벤트기반 인터페이스(SAX)는
 문서 요소에 대해 트리구조를 생성하지 않는다는 것이다. 이러한 점으로 인해 응용프로그램에서는 
 이벤트에서 발생한 정보에 대한 처리가 다소 복잡해질 수 있다. 

이벤트 기반 인터페이스는 객체 기반 인터페이스보다 하위 레벨에 속한다.    


 ▶ 현재 Java SAX Parser의 종류에는 어떤 것들이 있는가?

   - Xerces
        Apache Foundation, DOM & SAX
   - Crimson
        Sun Project X, JAXP Default Parser
   - JAXP
        Sun, Java API for XML Processing

먼저 Xerces는 SAX와 DOMahen를 다룰수 있게하는 XML API를 위하여 Apache Group의 프로젝트이다. 
현재 SAX1.0과 SAX2.0 API의 인터페이스가 지원이 되고 있으며, Xerces의 SAX패키지는 
org.apache.xerces.parser를 사용하고 있다.

Crimson은 Sun의 ProjectX의 일환으로 JAXP의 default parser로 채택되어져 있으며 XMLReader인터페이스를 
구현하므로 SAX API를 이용하여 여러가지 다양한 파싱기능을 사용할 수 있는 특징을 가지고 있다.

JAXP는 Xerces처럼 DOM과 SAX둘다를 사용할 수 있도록 지원해주는 API이다. 
한가지 다른 점이 있다면 SAX API의 인터페이스를 직접구현한 클래스를 제공하는 것이 아니라 
abstract계층을 한단계 더 얹은 형태를 제공한다. 
즉 개발자는 SAX API에 직접 접근하는 것이 아니라 파서의 종류에 따라 독립적인 프레임웍에 
접근한다고 보는 편이 좋을 것이다.

자 그러면 아래에서 코드를 보여주도록 하겠는데 첫번째로 Sun microsystems의 Default Parser인 
JAXP를 이용하여 간단한 SAX2 java프로그램을 작성해 보도록 한다.
또한 Xerces를 이용하여 변환가능한 SAX1, SAX2 프로그램을 작성해보도록 한다.
SAX2를 이용하여 실무에 적용할 수 있는 xml객체의 java object변환을 코드로 살펴보도록 한다.

먼저 각각에 대한 파서들을 다운받아 여러분들의 컴퓨터에 설치(사실 설치가 아니라 압축을 푼 후 
클래스 패스에 추가시키는 일이라 보는것이 무방하겠다)하도록 한다.


 ▶ 어디서 SAX파서들을 다운받을 수 있는가?

Xerces : http://xml.apache.org/xerces2-j/index.html
Crimson : http://xml.apache.org/crimson/index.html
JAXP : http://java.sun.com/xml

위의 사이트에서 다운로드 메뉴를 이용하여 각각의 파서들을 받아 여러분들의 컴퓨터에 XML이란 
디렉토리를 만든후 압축을 풀도록 하자.

SAX파서, 철저한 이벤트기반의 파서이다. 여러분들은 AWT, Swing같은 event핸들링 
코드를 작성해본적이 있는가? 

바로 이 SAX는 XML의 문장이 파서의 입력으로 들어오게되면 각 tag, attribute, content의 내용을 
하나의 입력이벤트로 바라보고, 각 요소들을 만났을 경우 해당이벤트를 여러분들이 작성한 
프로그램측으로 넘겨주게 된다.

1. 공통 핸들러 클래스의 작성
Handler class의 작성
1:		/*
2:    * @(#)ParserHandler.java	1.00 2002.08.05
3:    *
4:    * Copyleft Carouser
5:    * 
6:    */
7:    package com.javapattern;
8:   
9:    import javax.xml.parsers.SAXParser;
10:   import javax.xml.parsers.SAXParserFactory;
11:   import org.xml.sax.*;
12:   import org.xml.sax.helpers.*;

/** 중략 **/

22:   public class ParserHandler extends DefaultHandler{
23:   	private Locator loc;
24:   
25:   	public void startDocument() throws SAXException {
26:   	    System.out.println("startDocument method");
27:   	}
28:   	public void endDocument() throws SAXException {
29:   	    System.out.println("endDocument method");
30:   	}
31:   
32:   	public void characters(char[] ch, int start, int length) {
33:   	    System.out.println("Characters : " + new String(ch, start, length));
34:   	}
35:   public void startElement(String uri, String localName, 
                                              String qName, Attributes attr) {
36:   	System.out.println("Start Element : " + qName);	
37:   	int num = attr.getLength();
38:  	System.out.println("    Length  : " + num);
39:   
40:   	    //Display the attribute specification 
41:   	    for(int i = 0 ; i < num ; i++){
42:   		    System.out.println("    Name : " + attr.getLocalName(i));
43:   		    System.out.println("    Value : " + attr.getValue(i));
44:   	    }
45:   	}
46:   	public void endElement(String uri, String localName, String qName){
47:   	    System.out.println("End Element  : " + qName);
48:   	} // end of endElement
50:   } // end of class

Line 9, 10 : JAXP를 이용하여 위하여 SAXParser와 SAXParserFactory를 추가시킨다. JAXP는 모든 java API에 사용되는 일반적인 패턴인 factory패턴을 사용한다. 따라서 위의 SAXParserFactory의 클래스를 사용하여 XML파싱에 관련된 객체들을 생성해 낸다. 또한 위 facltory 클래스의 newSAXParser()메소드를 사용하면 SAX2 Parser객체를 생성해 낼 수 있는 것이다. Line 11 : XML spec에 정의한 interface를 선언한다. 여기서는 Attributes와 SAXParseException등을 사용하기 위하여 import시킨다. line 22 : 클래스의 선언, 현재 ParserHandler객체가 SAX2 event default인 DefaultHandler클래스의 타입이 되도록 선언한다. 핸들러클래스의 종류에는 EntityResolver, DTDHandler, ContentHandler, ErrorHandler가 있다. Line 23: Document location과 이용하여 SAX인터페이스를 구성한다. Line 25~28 : startElement()와 endElement()메소드는 document event parsing의 시작과 끝지점에서 호출된다. Line 32 : characters()메소드는 문자배열, 시작인덱스, 길이의 3개 인수로 구성이 되는데 문자배열은 파라미터로 전달된 문자이며, 이러한 start와 length만큼을 스트링 문자열로 변환시켜 표현할 수 있는데, 그 부분의 역할을 한다 Line 35 : Parser가 XML Element의 첫기호인 ‘<‘를 만나게 될 경우 호출되는 메소드인데, 여러개의 attribute들이 하나의 element들에 속할 수 있기 때문에 인수로서 Attributes클래스의 형태를 받을 수 있는데 이는 looping을 통하여 어떤 attribute들이 해당 element에 속하는지를 출력해 낼 수 있다. Uri와 localName은 파서가 namespace를 인식할 수 있는 경우에만 전달이 되면 qName은 언제나 해당 element의 이름이어야 한다. Line 46 : Parser가 element의 end tag인 '</'를 만났을 경우 호출이 된다. JAXP를 이용한 SAX2.0프로그래밍
9:    import javax.xml.parsers.SAXParser;
10:   import javax.xml.parsers.SAXParserFactory;
11:   import org.xml.sax.*;
12:   import org.xml.sax.helpers.*;
13:   import java.io.File;
23:   public class JAXPSample {
24:   	public static void main(String [] args) throws Exception {
25:   	    SAXParserFactory factory = SAXParserFactory.newInstance();
26:   	    SAXParser parser = factory.newSAXParser();
27:   	    DefaultHandler handler = new ParserHandler(); 
28:   
29:   	    parser.parse(new File(args[0]), handler);
30:   	    }
31:   }

Line 9~13 : Program에 필요한 package 및 class를 import시킨다. Line 25 : SAX parsing에 필요한 factory클래스에 대한 인스턴스를 얻도록 한다. Line 26 : newSAXParser는 javax.xml.parsers.SAXParser의 추상클래스를 상속받은 JAXP의 객체를 반환해준다. Line 27 : 이전 페이지에서 정의한 DefaultHandler클래스를 정의하여 각각의 SAX이벤트를 처리할 수 있도록 user define클래스인 ParserHandler의 객체를 생성하도록 한다. Line 29 : SAXParser의 핵심메소드인 parse()메소드를 이용하여 받아들인 파일객체를 파싱하도록 한다 Xerces를 이용한 SAX2.0프로그래밍
1:   package com.javapattern;
2:   
3:   import org.apache.xerces.parsers.SAXParser;
4:   import org.xml.sax.ContentHandler;
5:   import org.xml.sax.XMLReader;
6:   import org.xml.sax.InputSource;
7:   import java.io.FileReader;
8:   
9:   public class XercesSample {
10:   	public static void main(String [] args) throws Exception {
11:   	    //SAX1.0
12:       //Parser parser = new SAXParser();
13:   	    //SAX2.0
14:   	    XMLReader reader = new SAXParser();
15:   	    InputSource source = new InputSource(new FileReader(args[0]));
16:   	    ContentHandler handler = new ParserHandler(); 
17:   	    reader.setContentHandler(handler);
18:   	    reader.parse(source);
19:   	}
20:   }

위의 프로그램은 event handler클래스로서 앞서 정의한 ParserHandler 클래스를 이벤트클래스로 등록시켜 사용하므로 코드는 윗부분에 나와있다. Line 12 : Xerces같은 경우 SAX1과 SAX2에 모두 적용시킬 수 있는 API의 묶음으로 각각의 상황에 서로 다른 정의를 내릴 수 있는데 Parser인터페이스에 SAXParser라는 객체를 생성하여 할당함으로서 SAX1.0버젼의 parser를 사용할 수 있다. Line 14 : SAX2.0의 파싱에 사용되는 클래스로서는 XMLReader라는 인터페이스를 사용할 수 있다. Line 15 : 파싱에 사용될 InputSource객체를 생성하게 되는데 위의 코드에서는 입력받은 xml파일을 이용하여 처리하게 된다. Line 16, 17 : 우리가 정의한 ParserHandler를 이용하여 객체를 생성한 다음 14번라인에서 정의한 xml파서의 handler로서 등록하게 한다. Line 18 : XMLReader의 parse()메소드를 이용하여 처리한다. Sample XML문서
<?xml version="1.0" ?>
<Profile>
	<Person>
		<FirstName>JiWoong</FirstName>
		<LastName>Choi</LastName>
		<Age>30</Age>
		<Height>181</Height>
		<Job>Java Developer</Job>
	</Person>
	<Person>
		<FirstName>HongSeong</FirstName>
		<LastName>Jeon</LastName>
		<Age>33</Age>
		<Height>177</Height>
		<Job>Java Architect</Job>
	</Person>
</Profile>

실행방법 set SAMPLE_HOME=당신이 설치한 XML파서를 위한 jar파일이 있는 디렉토리 javac -classpath .;%SAMPLE_HOME%\crimson.jar;%SAMPLE_HOME%\jaxp.jar; -d . %1 %2 %3 %4 %5 java -classpath .;%SAMPLE_HOME%\crimson.jar;%SAMPLE_HOME%\jaxp.jar; %1 %2 %3 %4 %5 위와 같은 명령어를 갖는 shell이나 batch파일을 만들어서 사용하는것이 훨씬 수월할 것이다. 이상으로 간단하게 SAX의 개요와 프로그래밍 방법에 대하여 보았다. 의외로 XML은 심플하게 접근할 수 있는 특징을 가지고 있다. 요즘에는 XML editor들이 잘 나와있어서 그런 것들을 이용하여 쉽게 작성할 수 있으며, 이러한 내용을 알게 된다면 훨씬 더 효과적으로 환경 및 데이터 전송등이 사용할 수 있다라는 것을 명심하자.
 
1
References
 
Xerces : http://xml.apache.org/xerces2-j/index.html
Crimson : http://xml.apache.org/crimson/index.html
JAXP : http://java.sun.com/xml
http://www.w3c.org This Article Source : SAXTest.zip
Copyright ⓒ 2003 www.javapattern.info & www.jlook.com, an jLOOK co.,LTD