JAVA XML 파일 읽어 오기 DOM, SAX 사용 방법

자바에서 XML 파일을 사용하는 경우가 있습니다.

XML이란 Extensible Markup Language의 약어입니다.

마크업 언어로 WEB사이트 디자인에 사용되는 HTML과 비슷합니다.

마크업 언어는 항목과 값이 세트로 이루어진 언어입니다.

항목과 값이 세트로 되어 있기 때문에 데이터의 저장 또는 설정 값을 저장할 때 많이 사용됩니다.

XML 파일이 작성되어있는 간단한 예를 먼저 보겠습니다.

Sample.xml

<?xml version="1.0" encoding="UTF-8"?>
<info code="A01">
    <name>Test Data</name>
</info>

 

위처럼 작성되어 있는 XML 파일을 읽어와 자바에서 사용할 수 있습니다.

XML 파일을 읽어오는 방법으로 DOM과 SAX을 사용할 수 있습니다.

  • DOM – 요소가 노드로 형태로 구성되어 있으며, 노드의 관계가 노드 트리로 관리됨.
  • SAX – 요소를 앞에서부터 순서대로 하나씩 읽어옴.

 

DOM

DOM을 사용해 XML 파일에 작성한 정보를 읽어오는 방법을 알아보겠습니다.

DOM은 javax.xml.parsers패키지의 DocumentBuilder클래스와 DocumentBuilderFactory클래스를 사용합니다.

샘플로 작성했던 Sample.xml을 읽어오는 예제를 보겠습니다.

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(new File("Sample.xml"));

 

Sample.xml 파일을 읽어와 정보를 저장하는 변수는 doc가 됩니다.

doc 변수에 다시 접근해 Sample.xml 파일에서 요소를 취득하기 위해서는 getDocumentElement를 사용합니다.

Element element = doc.getDocumentElement();
System.out.println("Node: " + element.getNodeName());
System.out.println("code: " + element.getAttribute("code"));

 

XML 파일을 작성할 때에 노드 안에 노드를 작성할 수 있습니다.

이러한 노드는 자식 노드가 됩니다.

자식 노드를 취득하기 위해서는 getChildNodes 메서드를 사용합니다.

NodeList nodeList = element.getChildNodes();
for(int i = 0; i < nodeList.getLength(); i++) {
    Node node = nodeList.item(i);
    if(node.getNodeType() == Node.ELEMENT_NODE) {
        Element name = (Element)node;
        if(name.getNodeName().equals("name")) {
            System.out.println(name.getNodeName() + ": " + name.getTextContent());
        }
    }
}

 

위 내용들을 정리해 XML 파일에서 요소들을 취득해오는 샘플을 확인해보겠습니다.

import java.io.File;
 
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
 
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
 
public class XMLsample {
 
    public static void main(String[] args) {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        try {
        
            // XML 파싱
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document doc = builder.parse(new File("Sample.xml"));
            
            // 
            Element element = doc.getDocumentElement();
            System.out.println("Node: " + element.getNodeName());
            System.out.println("code: " + element.getAttribute("code"));
 
            NodeList nodeList = element.getChildNodes();
            for(int i = 0; i < nodeList.getLength(); i++) {
                Node node = nodeList.item(i);
                
                // 노드의 타입이 Element일 경우(공백이 아닌 경우)
                if(node.getNodeType() == Node.ELEMENT_NODE) {
                    Element name = (Element)node;
                    if(name.getNodeName().equals("name")) {
                        System.out.println(name.getNodeName() + ": " + name.getTextContent());
                    }
                }
            }
 
        } catch (Exception e) {
            e.printStackTrace();
        }
     }
 }

 

결과

Node: info
code: A01
name: Test Data

 

SAX

이번에는 SAX를 사용해 XML 파일을 읽어오는 방법을 확인해보겠습니다.

SAX는 javax.xml.parsers패키지의 SAXParser클래스와 SAXParserFactory클래스를 사용합니다.

SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
parser.parse(new File("Sample.xml"), new SAXsample());

 

SAX의 API의 경우는 org.xml.sax.helpers.DefaultHandler클래스를 계승하고, 각각의 이벤트 처리를 작성합니다.

예를 들어 문서 읽기가 시작된 경우는 startDocument메서드에 작성한 내용이 실행됩니다.

그리고 시작 노드에 도착한 경우에는 startElement메서드에 작성한 내용이 실행됩니다.

class SAXsample extends DefaultHandler{
    public void startDocument() {
        System.out.println("파일 읽기 시작");
    }
 
    public void endDocument() {
        System.out.println("파일 읽기 종료");
    }
 
    // 엘리먼트 시작
    public void startElement(String uri, String localName, String qName, Attributes attributes) {
        System.out.println("Node: " + qName + " Start");
        if(qName.equals("info")) {
            System.out.println(attributes.getQName(0) + ": " + attributes.getValue(0));
        }
    }
 
    // 엘리먼트 끝
    public void endElement(String uri, String localName, String qName) {
        System.out.println("Node: " + qName + " End");
    }
 
    // 텍스트 데이터
    public void characters(char[] ch, int start, int length) {
        System.out.println(new String(ch, start, length));
    }
}

 

샘플 소스를 보면서 SAX 사용 방법을 확인해보겠습니다.

import java.io.File;
 
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
 
import org.xml.sax.Attributes;
import org.xml.sax.helpers.DefaultHandler;
 
class XMLsample{
 
    public static void main(String[] args) {
        SAXParserFactory factory = SAXParserFactory.newInstance();
        try {
            SAXParser parser = factory.newSAXParser();
            parser.parse(new File("Sample.xml"), new SAXsample());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
 
class SAXsample extends DefaultHandler{
    public void startDocument() {
        System.out.println("파일 읽기 시작");
    }
 
    public void endDocument() {
        System.out.println("파일 읽기 종료");
    }
    
    // 엘리먼트 시작
    public void startElement(String uri, String localName, String qName, Attributes attributes) {
        System.out.println("Node: " + qName + " Start");
        if(qName.equals("info")) {
            System.out.println(attributes.getQName(0) + ": " + attributes.getValue(0));
        }
    }
 
    // 엘리먼트 끝
    public void endElement(String uri, String localName, String qName) {
        System.out.println("Node: " + qName + " End");
    }
 
    // 텍스트 데이터
    public void characters(char[] ch, int start, int length) {
        System.out.println(new String(ch, start, length));
    }
}

 

결과

파일 읽기 시작
Node: info Start
code: A01
 
Node: name Start
Test Data
Node: name End
 
Node: info End
파일 읽기 종료

 

SAX을 사용해 XML 파일을 읽어오면 파일 안의 내용을 순차적으로 읽어, 시작 엘리먼트나 속성, 종료 엘리먼트, 텍스트 데이터 등을 만나면 이벤트가 발생하여 각 구성 요소를 처리하는 메서드가 호출됩니다.

그리고 호출된 메서드에 작성된 처리가 실행이 됩니다.

XML 파일을 읽어와 요소를 취득하는 방법을 알아봤습니다.

DOM방식은 파일을 읽어와 메모리에 모두 로드한 후 파싱 하고,

SAX는 순차적으로 읽어가며 파싱을 합니다.

상황에 따라 적절한 방법을 선택하여 사용하면 좋을 거 같습니다.

댓글