간단하게 설명이 잘되어져 있는 포스트를 링크합니다 ^ ^

http://blog.naver.com/swinter8/130000715438

SAX 와 DOM 의 장단점을 잘 파악해서 사용하는것이 좋겠지요. 무엇이 더 좋다라고는 판단못할것같군요^^




SAX (Simple API for XML)

두가지 파서

  • 객체 기반 (Object-based) Interface : DOM
    • 메모리 상주 트리 이용, 문서 전체를 로드
    • 응용에서 간단히 사용
  • 이벤트 기반 (Event-driven) Interface : SAX
    • 문서를 순서대로 읽어 들이면서 해당 메소드를 처리
    • 파서가 간단, 응용프로그램은 복잡
       

SAX history

설치

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:>_

문서 변환 예제

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
페이스북 댓글
티스토리 댓글

+ Recent posts