SAX (Simple API for XML)
두가지 파서
- 객체 기반 (Object-based) Interface : DOM
- 메모리 상주 트리 이용, 문서 전체를 로드
- 응용에서 간단히 사용
- 이벤트 기반 (Event-driven) Interface : SAX
- 문서를 순서대로 읽어 들이면서 해당 메소드를 처리
- 파서가 간단, 응용프로그램은 복잡
SAX history
- W3C 표준이 아니다, OASIS 그룹(http://www.oasis-open.org/)에서 시작,
- David Megginson이 관리/조정 (http://www.megginson.com에 정보)
- 1998.5월 SAX 1.0, 2000.5월 SAX 2.0 발표
설치
- JAXP (Java for XML Parser) - Sun : http://java.sun.com/xml/jaxp/index.html
- XML4J (XML Parser for Java) - IBM : http://www.alphaworks.ibm.com/tech/xml4j
- Xerces Java Parser - Apache : http://xml.apache.org
- 기타 교재 p.464
SAX 구조 모델 : 이벤트 기반 인터페이스
- XML 문서에서 발생되는 이벤트
- 문서 시작/종료, 시작태그, 종료태그, 엘리먼트 내용, 엔티티, 오류 등
- 이벤트 발생 예
이벤트 발생 시점 이벤트 핸들러 ①
<list>②
<book InStock="0">③*
<title>④XML 클래스⑤</title>⑥
<author>⑦임순범⑧</author>⑨
<pages/>⑩⑪**
<price>⑫19000⑬</price>⑭
</book>⑮
</list>①'
②'①startDocument()
②startElement()
③startElement() *속성은 매개변수로 전달
④startElement() ⑤characters() ⑥endElement()
⑦startElement() ⑧characters() ⑨endElement()
⑩startElement() ⑪endElement() ** 이벤트 2회
⑫startElement() ⑬characters() ⑭endElement()
⑮endElement() 속성은 매개변수로 전달
①'endElement()
②'endDocument()
SAX 프로그래밍 구조
- 이벤트 프로그래밍
- 파서에서 이벤트를 발생했을 때 => 설정되어 있는 해당 메소드를 호출
- 해당 메소드(이벤트 핸들러)를 작성
import java.io.*;
import javax.xml.parsers.*;
import org.xml.sax.*;
import org.xml.sax.helpers.*;
public class MySAX
{
public static void main(String[] args) throws Exception
{
if (args.length < 1) ...에러메시지...
SAXParserFactory factory =
SAXParserFactory.newInstance( );
SAXParser parser = factory.newSAXParser( );
EvtHandler handler = new EvtHandler();
parser.parse(new FileInputStream(args[0]), handler);
}
}
public class EvtHandler extends DefaultHandler
{
public void startDocument( ) { ... }
public void endDocument( ) { ... }
...
}필요한 클래스 포함
핸들러 클래스 정의
테스트 클래스
메인
parser factory 생성
parser 생성
event handler 생성
parser 호출/실행시
event handler 할당
핸들러 클래스 정의
(DefaultHandler)
... 해당 메소드 ...
SAX API 의 주요 인터페이스 및 메소드
인터페이스 종류 |
지원되는 주요 메소드 |
XMLReader | parse(), getContentHandler(), getDTDHandler(), getEntityResolver(), getErrorHandler(), getFeature(), getProperty(), setContentHandler(), setDTDHandler(), setEntityResolver(), setErrorHandler(), setFeature(), setProperty() |
ContentHandler * |
startDocument(), endDocument(), setDocumentLocator(), ignorableWhitespace(), startElement(), endElement(),characters(), processingInstruction(), startPrefixMapping(), endPrefixMapping() |
DTDHandler * |
notationDecl(), unparsedEntityDecl() |
EntityResolver * |
resolveEntity(), skippedEntity() |
ErrorHandler * |
warning(), error(), fatalError() |
Attributes |
getLength(), getQName(i), getLocalName(), getIndex(), getType(i),getValue(i), getURI() |
Locator |
getColumnNumber(), getLineNumber(), getPublicId(), getSystemId() |
* DefaultHandler 클래스는 ContentHandler, DTDHandler, EntityHandler, ErrorHandler 인터페이스를 모두 구형한 클래스
SAX API 이벤트 핸들러
- 기본 예제
- public void startDocument( ) { ... }
- public void endDocument( ) { ... }
- public void startElement(String uri, String localName, String qName, Attributes atts) ...
- public void endElement(String uri, String localName, String qName) ...
import java.io.*;
import javax.xml.parsers.*;
import org.xml.sax.*;
import org.xml.sax.helpers.*;
public class reader1
{
public static void main(String[] args) throws Exception
{
if (args.length < 1)
System.out.println("... java reader1 filename...");
SAXParserFactory factory =
SAXParserFactory.newInstance( );
SAXParser parser = factory.newSAXParser( );
myreader handler = new myreader();
parser.parse(new FileInputStream(args[0]), handler);
}
}
public class myreader extends DefaultHandler
{
public void startDocument( )
{ System.out.println("...startDocument"); }
public void endDocument( )
{ System.out.println("...endDocument"); }
public void startElement(String uri, String localName,
String qName, Attributes atts)
{ System.out.print("<"+qName+">"); }
public void endElement(String uri, String localName,
String qName)
{ System.out.println("</"+qName+">");}
}실행
C:>javac reader1.java
C:>java reader1 booklist.xml
결과
...startDocument
<list><book><title></title>
<author></author>
<pages></pages>
<price></price>
</book>
<book><title></title>
<author></author>
<pages></pages>
<price></price>
</book>
<book><title><subtitle></subtitle> </title>
<author></author>
<pages></pages>
<price></price>
</book>
...endDocument
- 문자 데이터 처리하기
- public void characters(char[] chars, int start, int length) { ... }
import ...
public class reader2
{
public static void main(String[] args) throws Exception
{
if (args.length < 1)
System.out.println("... java reader2 filename...");
SAXParserFactory ...
myreader2 handler = new myreader2();
parser.parse(new FileInputStream(args[0]), handler);
}
}
public class myreader2 extends DefaultHandler
{
public void startDocument( ) { ... }
public void endDocument( ) { ... }
public void startElement(String uri, ...) { ... }
public void endElement(String uri, String localName,
String qName)
{ System.out.print("</"+qName+">"); }
public void characters(char[] chars, int start, int leng)
{
for (int i=0;i<leng;i++)
System.out.print(chars[start+i]);
}
}실행
C:>javac reader2.java
C:>java reader2 booklist.xml
...startDocument
<list>
<book>
<title>XML Bible</title>
<author>Gwyneth Paltrow</author>
<pages>652</pages>
<price>39.99</price>
</book>
<book>
<title>XML 클래스</title>
<author>임순범</author>
<pages>458</pages>
<price>19000</price>
</book>
<book>
<title>
<subtitle>열혈강의</subtitle>
XML By Example</title>
<author>홍길동</author>
<pages>529</pages>
<price>25000</price>
</book>
</list>...endDocument
- 원하는 문자 데이터만 선택하여 출력
import ...
public class reader3
{
public static void main(String[] args) throws Exception
{
... myreader3 handler = new myreader3(); ...
}
}
public class myreader3 extends DefaultHandler
{
private StringBuffer titles = new StringBuffer();
private StringBuffer authors = new StringBuffer();
private boolean isTitle, isAthor = false;
private int num=1;
public void startElement(String uri, String localName,
String qName, Attributes atts)
{
if (qName.equals("title")) {
isTitle=true; titles.setLength(0);
} else if (qName.equals("author")) {
isAuthor=true; authors.setLength(0);
}
}
public void endElement(String uri, String localName,
String qName)
{
if (qName.equals("book")){
System.out.println("["+num+"] "+
authors.toString()+", "+titles.toString());
num++;
}
}
public void characters(char[] chars, int start, int leng)
{
if (isTitle) {
isTitle=false; titles.append(chars,start,leng);
} else if (isAuthor) {
isAuthor=false; authors.append(chars,start,leng);
}
}
}실행
C:>javac reader3.java
C:>java reader3 booklist.xml
[1] Gwyneth Paltrow, XML Bible
[2] 임순범, XML 클래스
[3] 홍길동,
C:>_- 수정
...
public void endElement(String uri, ...)
{
if (qName.equals("book")){
System.out.println("[" + num + "] "
+ authors.toString() + "," + titles.toString());
num++;
} else if (isTitle) isTitle = false;
else if (isAuthor) isAuthor = false;
}
public void characters( ... )
{
if (isTitle) titles.append(chars,start,leng);
else if (isAuthor) authors.append(chars,start,leng);
}
실행
C:>javac reader3.java
C:>java reader3 booklist.xml
[1] Gwyneth Paltrow, XML Bible
[2] 임순범, XML 클래스
[3] 홍길동,
열혈강의
C:>_
- 속성 읽기
- void startElement(String uri, String localName, String qName, Attributes atts) ...
- atts.getValue("속성명"), getLength(), getQName(번호), getValue(번호)
...
public class myreader4 extends DefaultHandler
{
private ... titles, authors, isTitle, isAthor, num ... ;
private String stock = new String();
public void startElement(String uri, String localName,
String qName, Attributes atts)
{
if (qName.equals("book"))
stock = atts.getValue("InStock");
else if (qName.equals("title")) {
isTitle=true; titles.setLength(0);
} else if (qName.equals("author")) {
isAuthor=true; authors.setLength(0);
}
}
public void endElement(String uri, ...)
{
if (qName.equals("book")){
System.out.println("["+num+"] "+
authors...+"(재고:"+stock+"권)");
num++;
}
}
public void characters(char[] chars, ...) ...
}실행
C:>javac reader4.java
C:>java reader4 booklist.xml
[1] Gwyneth Paltrow, XML Bible(재고:2권)
[2] 임순범, XML 클래스(재고:0권)
[3] 홍길동,
열혈강의(재고:8권)
C:>_
- void startElement(String uri, String localName, String qName, Attributes atts) ...
문서 변환 예제
import java.io.*; import javax.xml.parsers.*; import org.xml.sax.*; import org.xml.sax.helpers.*; public class conv { public static void main(String[] args) throws Exception { if (args.length < 1) System.out.println("...java reader1 filename"); SAXParserFactory factory = SAXParserFactory.newInstance( ); SAXParser parser = factory.newSAXParser( ); myconv handler = new myconv( ); parser.parse(new FileInputStream(args[0]), handler); } } public class myconv extends DefaultHandler { private int nspace = 4; // indentation spaces private int indent = 0; // indentation level private boolean inTag=false; public void setDocumentLocator(Locator loc) { System.out.println("[파일] "+loc.getSystemId()); } public void startDocument( ) { System.out.print("==============="); } public void endDocument( ) { System.out.println("==============="); } public String spaces(int num) { String str = ""; if (num > 0) for (int i=0; i<num; i++) str += " "; return str; } public void startElement(String uri, String lname, String qname, Attributes atts) { String str = spaces(indent*nspace); if (inTag) System.out.println(); System.out.print(str + "<" + qname); int leng = atts.getLength(); if (leng > 0) for (int i=0; i<leng; i++) System.out.print(" " + atts.getQName(i)+"=""+atts.getValue(i)+"""); System.out.print(">"); indent++; inTag=true; } |
public void endElement(String uri, String lname, String qname) { System.out.println("</" + qname + ">"); indent--; inTag=false; } public void characters(char[] ch, int start, int length) { String str=""; if (length == 0) return; for (int i=0; i<length; i++) if (ch[start+i] != ' ') str += ch[start+i]; str = str.trim(); if (str != "") System.out.print(str); } public void processingInstruction (String target, String data) { System.out.print(" <? "+target+" "+data+" ?>"); } } |
실행 C:>javac conv.java C:>java conv booklist.xml [파일] file:/C:/Lec/XML02/booklist.xml =============== <? xml-stylesheet type="text/xsl" href="booklist.xsl" ?> <list> <book InStock="2"> <title>XML Bible</title> <author>Gwyneth Paltrow</author> <pages>652</pages> <price currency="usd">39.99</price> </book> <book InStock="0"> <title>XML 클래스</title> <author>임순범</author> <pages>458</pages> <price>19000</price> </book> <book InStock="8"> <title> <subtitle>열혈강의</subtitle> XML By Example</title> <author>홍길동</author> <pages>529</pages> <price>25000</price> </book> </list> =============== |
SAX 이벤트 프로그래밍
- 이벤트 기반 인터페이스 장단점
- DOM보다 하위 레벨 => 파싱하는 동안 많은 기능 제공 가능 => 응용 최적화
- 문서를 읽는 동안 처리 가능, 적은 시스템 자원 사용 => 큰 문서, 많은 문서 처리시 효과
- [단점] 응용 프로그램에서 많은 작업
- [단점] 문서 일부분에 대한 임의 접근 불가능, 이벤트 및 작업 상태 보관 필요성
- DOM 과 SAX 비교
DOM
SAX
접근 방법 트리 기반 이벤트 기반 장점 문서에 임의 접근 메모리 효율, 빠른 속도 단점 메모리 사용량, 속도 느리다 구조에 대한 접근 곤란, 읽기 전용,
브라우저 지원 안됨적용분야 구조적 접근이 필요한 경우,
문서 정보를 쉽게 파악하고자 할 때문서 일부분만 읽을 때,
데이터 변환시, 유효성 처리
'Programming' 카테고리의 다른 글
이공계기피현상의 글을 읽은 현 개발자의 푸념. (63) | 2008.10.07 |
---|---|
STRNCPY, strncpy, strcpy (0) | 2008.10.06 |
jdbc (0) | 2008.09.25 |
LPAcampus 강좌 (0) | 2008.09.22 |
JAVA byte[] <-> String (0) | 2008.09.19 |