반응형
출처: http://kr.blog.yahoo.com/kwon37xi/folder/3381246.html
Java와 XML 2판의 내용정리이다.
책을 보지 않으면 이 내용을 이해할 수 없을 수 있다.

SAX 파서는 XML 문서를 순차적으로 분서하는데 문서를 분석하는 동안 시작 태그나 속성, 종료 태그, 텍스트 데이터 등을 만나면 각 구성 요소를 처리하는 메소드를 호출한다.
이때 메소드를 호출하는 구성요소를 만나는 것이 이벤트가 된다. 즉, SAX 파서가 시작태그를 만나는 것이 하나의 이벤트이고 속성을 만나는 것이 또 다른 이벤트가 된다. 그리고 각 구성요소를 처리하는 메소드를 호출하는 것은 이벤트를 처리한다라고 표현하며, 호출되는 메소드를 콜백(callback) 메소드라고 부른다.

SAX Parser

http://xml.apache.org 에서 Xerces 파서를 구할 수 있다.

SAX 클래스는 org.xml.sax 구조로 패키징되어 있다. 최소한 org.xml.sax.XMLReader 클래스가 있어야 한다.

SAX 공식 홈 : http://wwww.saxproject.org

SAXReader

SAX 사용의 시작은 org.xml.sax.XMLReader 의 객체를 얻는 것이다.
// 파서 클래스 지정. 여기서는 아파치 Xerces
private String parserClass="org.apache.xerces.parsers.SAXParser";

// 파싱에 사용할 XMLReader 객체 생성
XMLReader reader = XMLReaderFactory.createXMLReader(parserClass);

  • XMLReader 의 객체는 재사용이 가능하지만 한 번에 한개의 XML 파일만을 파싱해야한다.

XML 문서 파싱

XMLReader 객체의 parse(InputSource) 혹은 parse(String URI)로 파싱한다. InputSource 사용권장.

InputSource is = new InputSource(new FileInputStream(new File(xmlURI)));

// 필수적으로 SystemID를 설정해야 한다.
// SystemID는 XML 문서의 URI이다.(파일의 경우 파일의 경로)
is.setSystemId(xmlURI);

// 파싱
reader.parse(inputSource);
  • 항상 시스템 ID를 설정해야만 한다!!
  • SystemID는 XML문서의 URI이다. 파일의 경우는 파일의 경로를 의미한다.

Handler 등록

핸들러는 SAX 파서가 문서를 순차적으로 분석하는 동안 발생한 이벤트에 대해 호출할 메소드를을 가진 클래스 객체이다.

  • XMLReader.setContentHandler()
  • XMLReader.setErrorHandler()
  • XMLReader.setDTDHandler()
  • XMLReader.setEntityHandler()


  • 모든 핸들러는 throws SAXException 을 해야 한다.

Content Handler

  • 요소 등 XML의 내용을 만났을때 호출되는 콜백 메소드를 가지는 클래스.
  • ContentHandler 인터페이스 구현

public void setDocumentLocator(Locator locator)

  • 분석중인 문서의 위치 정보를 가진 Locator의 객체 생성. Locator 객체의 getLineNumber(), getColumnNumber() 메소드들로 이벤트가 발생한 위치를 알아낼 수 있다.
  • 이벤트의 위치는 실제 처리중인 분석과정에만 유효. Locator는 ContentHandler를 구현한 클래스 범위 내에서만 사용되어야 한다! Locator를 ContentHandler 의 인스턴스 멤버로 등록한다.

public void startDocument() throws SAXException

  • 문서 시작시 호출되는 콜백 메소드.
  • 모든 핸들러를 포함하여 가장 처음에 호출.(setDocumentLocator() 제외)

public void endDocument() throws SAXException

  • 문서 분석이 끝날 때 호출되는 콜백 메소드
  • 모든 핸들러를 포함하여 가장 나중에 호출.

public void processingInstruction(String target, String data)

  • 처리지시어(<? --- ?>)를 처리한다.
  • XML 데이터를 사용하는 실제 애플리케이션은 이 메소드로 처리 지시어를 받아 변수 값을 설정하거나 특정한 처리 과정을 수행하는 메소드를 실행한다.
  • <?xml version="1.0"?> 이 부분은 전달되지 않는다.

네임스페이스 매핑

  • 네임스페이스를 선언하는 xmlns 를 만나면 발생
  • public void startPrefixMapping(String prefix, String uri)
  • public void endPrefixMapping(String prefix)
  • 프로그래밍 패턴

    private Map namespaceMappings = new HashMap();
    
    public void startPrefixMapping(String prefix, String uri) {
    	// 시각적인 이벤트는 발생하지 않는다.
    	namespaceMappings.put(uri, prefix);
    }
    
    public void endPrefixMapping(String prefix) {
    	// 시각적인 이벤트는 발생하지 않는다.
    	for (Iterator i = namespaceMappings.keySet().iterator(); i.hasNext(); ) {
    		String uri = (String)i.next();
    		String thisPrefix = (String)namespaceMappings.get(uri);
    		if (prefix.equals(thisPrefix)) {
    			namespaceMappings.remove(uri);
    			break;
    		}
    	}
    }
    

public void startElement(String namespaceURI, String localName, String qName, Attributes atts)

  • 요소가 시작될 때 호출
  • qName 은 네임스페이스 접두어가 있다면 그것을 이름에 포함한다.
  • atts 는 요소의 속성들을 배열로 가지고 있다.

public void endElement(String namespaceURI, String localName, String qName, Attributes atts)

  • 요소가 닫힐 때 호출

public void characters(char[] ch, int start, int length)

  • 요소의 텍스트 데이터
  • ch 배열의 start 인덱스부터 length 길이 만큼 만이 데이터이다!!

public void ignorableWhitespace(char[] ch, int start, int length)

  • 무시 가능한 공백문자가 올 경우 호출
  • DTD나 스키마가 없으면 호출되지 않는다. DTD나 스키마에서 무시가능한 공백문자를 지정하기 때문이다.

public void skippedEntity(String name)

  • 파서가 엔티티를 처리하지 않을 때 호출
  • 실제 이 메소드가 호출되는 경우는 거의 없다.(Xerces는 절대 호출하지 않는다.)
  • 이 콜백을 수행하면 엔티티 참조의 앞의 앰퍼샌드와 뒤의 세미콜론을 포함하지 않는 엔티티 참조를 매개변수로 전달한다.

ErrorHandler

  • 파싱중 오류가 발생하면 호출되는 핸들러
  • ErrorHandler 인터페이스 구현

public void warning(SAXParseException ex)

  • 경고

public void error(SAXParseException ex)

  • 치명적이지 않은 오류

public void fatalError(SAXParseException ex)

  • 치명적 오류
  • 파싱을 중지하는게 낫다.

+ Recent posts