웹사이트 검색

자바 SAX 파서 예제


Java의 SAX Parser는 XML 문서를 구문 분석하기 위한 API를 제공합니다. SAX 파서는 완전한 XML을 메모리에 로드하지 않고 XML 문서를 순차적으로 읽지 않는다는 점에서 DOM 파서와 다릅니다.

SAX 파서

SAX 파서 예

이제 SAX 파서 예제 프로그램으로 넘어가겠습니다. 나중에 다른 기능에 대해 자세히 설명하겠습니다. employees.xml

<?xml version="1.0" encoding="UTF-8"?>
<Employees>
	<Employee id="1">
		<age>29</age>
		<name>Pankaj</name>
		<gender>Male</gender>
		<role>Java Developer</role>
	</Employee>
	<Employee id="2">
		<age>35</age>
		<name>Lisa</name>
		<gender>Female</gender>
		<role>CEO</role>
	</Employee>
	<Employee id="3">
		<age>40</age>
		<name>Tom</name>
		<gender>Male</gender>
		<role>Manager</role>
	</Employee>
	<Employee id="4">
		<age>25</age>
		<name>Meghna</name>
		<gender>Female</gender>
		<role>Manager</role>
	</Employee>
</Employees>

따라서 파일 시스템 어딘가에 XML 파일이 저장되어 있고 이를 살펴보면 직원 목록이 포함되어 있다는 결론을 내릴 수 있습니다. 모든 직원은 id 속성과 age, name, genderrole 필드를 가집니다. SAX 파서를 사용하여 이 XML을 파싱하고 Employee 객체 목록을 생성합니다. 다음은 XML의 Employee 요소를 나타내는 Employee 개체입니다.

package com.journaldev.xml;

public class Employee {
    private int id;
    private String name;
    private String gender;
    private int age;
    private String role;
    
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getGender() {
        return gender;
    }
    public void setGender(String gender) {
        this.gender = gender;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getRole() {
        return role;
    }
    public void setRole(String role) {
        this.role = role;
    }
    
    @Override
    public String toString() {
        return "Employee:: ID="+this.id+" Name=" + this.name + " Age=" + this.age + " Gender=" + this.gender +
                " Role=" + this.role;
    }
    
}

DefaultHandler 클래스를 확장하는 고유한 SAX Parser Handler 클래스를 만들어 봅시다.


package com.journaldev.xml.sax;

import java.util.ArrayList;
import java.util.List;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import com.journaldev.xml.Employee;

public class MyHandler extends DefaultHandler {

	// List to hold Employees object
	private List<Employee> empList = null;
	private Employee emp = null;
	private StringBuilder data = null;

	// getter method for employee list
	public List<Employee> getEmpList() {
		return empList;
	}

	boolean bAge = false;
	boolean bName = false;
	boolean bGender = false;
	boolean bRole = false;

	@Override
	public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {

		if (qName.equalsIgnoreCase("Employee")) {
			// create a new Employee and put it in Map
			String id = attributes.getValue("id");
			// initialize Employee object and set id attribute
			emp = new Employee();
			emp.setId(Integer.parseInt(id));
			// initialize list
			if (empList == null)
				empList = new ArrayList<>();
		} else if (qName.equalsIgnoreCase("name")) {
			// set boolean values for fields, will be used in setting Employee variables
			bName = true;
		} else if (qName.equalsIgnoreCase("age")) {
			bAge = true;
		} else if (qName.equalsIgnoreCase("gender")) {
			bGender = true;
		} else if (qName.equalsIgnoreCase("role")) {
			bRole = true;
		}
		// create the data container
		data = new StringBuilder();
	}

	@Override
	public void endElement(String uri, String localName, String qName) throws SAXException {
		if (bAge) {
			// age element, set Employee age
			emp.setAge(Integer.parseInt(data.toString()));
			bAge = false;
		} else if (bName) {
			emp.setName(data.toString());
			bName = false;
		} else if (bRole) {
			emp.setRole(data.toString());
			bRole = false;
		} else if (bGender) {
			emp.setGender(data.toString());
			bGender = false;
		}
		
		if (qName.equalsIgnoreCase("Employee")) {
			// add Employee object to list
			empList.add(emp);
		}
	}

	@Override
	public void characters(char ch[], int start, int length) throws SAXException {
		data.append(new String(ch, start, length));
	}
}

MyHandler에는 Employee 개체 목록이 getter 메서드만 있는 필드로 포함되어 있습니다. Employee 개체가 이벤트 핸들러 메서드에 추가됩니다. 또한 직원 개체를 만드는 데 사용할 직원 필드가 있으며 모든 필드가 설정되면 직원 목록에 추가합니다.

재정의할 SAX 파서 메서드

재정의할 중요한 메서드는 startElement(), endElement()characters()입니다. SAXParser는 문서 구문 분석을 시작하고 시작 요소가 발견되면 startElement() 메서드가 호출됩니다. 이 메서드를 재정의하여 요소를 식별하는 데 사용할 부울 변수를 설정합니다. 우리는 또한 Employee 시작 요소가 발견될 때마다 새로운 Employee 객체를 생성하기 위해 이 방법을 사용하고 있습니다. Employee Object id 필드를 설정하려면 여기에서 id 속성을 읽는 방법을 확인하십시오. characters() 메서드는 요소 내부의 SAXParser에서 문자 데이터를 찾을 때 호출됩니다. SAX 파서는 데이터를 여러 청크로 나누고 characters() 메소드를 여러 번 호출할 수 있습니다(ContentHandler 클래스 characters() 메소드 문서 읽기). 이것이 우리가 StringBuilder를 사용하여 이 데이터를 append() 메서드를 사용하여 유지하는 이유입니다. endElement()는 직원 개체 속성을 설정하고 직원 끝 요소 태그를 찾을 때마다 직원 개체를 목록에 추가하기 위해 StringBuilder 데이터를 사용하는 곳입니다. 아래는 MyHandler를 사용하여 위의 XML을 직원 개체 목록으로 구문 분석하는 테스트 프로그램입니다.

package com.journaldev.xml.sax;

import java.io.File;
import java.io.IOException;
import java.util.List;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.SAXException;

import com.journaldev.xml.Employee;

public class XMLParserSAX {

    public static void main(String[] args) {
    SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
    try {
        SAXParser saxParser = saxParserFactory.newSAXParser();
        MyHandler handler = new MyHandler();
        saxParser.parse(new File("/Users/pankaj/employees.xml"), handler);
        //Get Employees list
        List<Employee> empList = handler.getEmpList();
        //print employee information
        for(Employee emp : empList)
            System.out.println(emp);
    } catch (ParserConfigurationException | SAXException | IOException e) {
        e.printStackTrace();
    }
    }

}

다음은 위 프로그램의 출력입니다.

Employee:: ID=1 Name=Pankaj Age=29 Gender=Male Role=Java Developer
Employee:: ID=2 Name=Lisa Age=35 Gender=Female Role=CEO
Employee:: ID=3 Name=Tom Age=40 Gender=Male Role=Manager
Employee:: ID=4 Name=Meghna Age=25 Gender=Female Role=Manager

SAXParserFactorySAXParser 인스턴스를 가져오는 팩토리 메서드를 제공합니다. 콜백 이벤트를 처리하기 위해 File 객체를 MyHandler 인스턴스와 함께 parse 메서드에 전달하고 있습니다. SAXParser는 처음에는 약간 혼란스럽지만 큰 XML 문서에서 작업하는 경우 DOM Parser보다 XML을 읽는 데 더 효율적인 방법을 제공합니다. 이것이 Java의 SAX Parser에 대한 전부입니다.

GitHub 리포지토리에서 프로젝트를 다운로드할 수 있습니다.

참조: DefaultHandler