JAXB 기초 (XML 파싱, 마샬, 언마샬 관련)

JAXB 기초 (XML 파싱, 마샬, 언마샬 관련)

 

자바의 XML을 파싱(분석)할 수 있게 도와주는 라이브러리로 JAXB가 있다. JAXB는 XML과 자바 클래스를 바인딩(연결)한다. 다시 말해 간단한 명령어만으로 클래스에 파싱된 XML을 대입해주는 라이브러리이다.

 

기존의 XML 분석 방법은 XML 전체를 String 형식으로 받아와서 문자열을 자르는 방식(substring)이었다. JAXB는 원하는 태그명, 어트리뷰트명을 기입한 클래스를 마련해두기만 하면 자동적으로 값이 클래스에 들어오게 되는 자동화 라이브러리이다.

 

 

1. 마샬(Marshal), 언마샬(Unmarshal)

XML을 파싱할 때 늘 나오는 개념이 언마샬(Unmarshal)과 마샬(Marshal)이다. 언마샬은 XML을 객체로 변환시키는 것이고, 마샬은 객체를 XML로 변환시키는 것이다.

 

 

2. 클래스(class), 값(value), 어트리뷰트(Attribute)

<all>

    <store>

        <itemName>치약</itemName>

        <price value=”2000″>2000</price>

    </store>

</all>

 

만약 <all><store><itemName>치약</itemName><price value=”2000″>2000</price></store></all> 라는 XML이 있다고 하자. 이 때 가장 안쪽에 위치하는 <itemName>, <price> 는 값에 해당한다. 그리고 값을 감싸고 있는 <all>과 <store>는 클래스라고 한다. 헷갈리지 않도록 주의할 점은, <store>가 클래스라는 점이다. 이와 같이 클래스 안에 클래스가 들어갈 수 있다. 특별히 <all>은 가장 위쪽에 위치한 클래스 이므로 루트(root)라고 부른다.

특히 값 중에서 <price>라는 값의 경우, value=”2000″이라는 정보를 태그 안에 갖고 있다. 여기서 value와 같은 요소를 어트리뷰트라고 한다.

 

 

3. JAXB의 활용
JAXB에서 root class에는 @XmlRootElement 라는 애너테이션(Annotation, 일종의 구분자. 골뱅이 모양이다)을 붙인다. 나머지 일반적인 class와 값에는 @XmlElement 라는 애너테이션을 붙인다. 자세한 사용법은 아래 자바 예제에서 확인할 수 있다.

 

 

4. 필요한 라이브러리 파일

JSOUP 라이브러리는 mvnrepository에서 구할 수 있다. 메이븐(Maven)을 쓰고 있다면 아래 코드를 붙여넣으면 된다.

 

<dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-core</artifactId>
    <version>2.2.11</version>
</dependency>
<dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-impl</artifactId>
    <version>2.2.11</version>
</dependency>

<dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
    <version>2.2.11</version>
</dependency>

 

 

5. 자바 예제

예제는 네이버 뉴스 댓글을 분석하는 자바 프로그램의 프로토타입이다.

Rss.java

package com.news;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Rss {
    private Channel channel;

    public Channel getChannel() {
        return channel;
    }

    @XmlElement
    public void setChannel(Channel channel) {
        this.channel = channel;
    }
}

 

Channel.java

ppackage com.news;

import javax.xml.bind.annotation.XmlElement;
import java.util.*;

public class Channel {
    private List<Item> item;

    public List<Item> getItem() {
        return item;
    }
    @XmlElement
    public void setItem(List<Item> item) {
        this.item = item;
    }
}

 

Item.java

package com.news;

import javax.xml.bind.annotation.XmlElement;

public class Item {
    private String title;
    private String link;
    private String description;
    public String getTitle() {
        return title;
    }
    @XmlElement
    public void setTitle(String title) {
        this.title = title;
    }
    public String getLink() {
        return link;
    }
    @XmlElement
    public void setLink(String link) {
        this.link = link;
    }
    public String getDescription() {
        return description;
    }
    @XmlElement
    public void setDescription(String description) {
        this.description = description;
    }
}

 

 

NewsManager.java

package com.news;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;

import java.net.*;
import java.util.*;

public class NewsManager {
   
    private String targetUrl = “http://newssearch.naver.com/search.naver?where=rss&query=“;
   
    public static void main(String[] args){
        NewsManager m = new NewsManager();
        List<Item> list=m.newsListData(“주가”);
        for(Item i:list){
            System.out.println(i.getTitle() + ” ” + i.getDescription());
        }
    }

    public List<Item> newsListData(String ss){
        
        List<Item> list = new ArrayList<Item>();
        try{
            JAXBContext jc=JAXBContext.newInstance( Rss.class );
            Unmarshaller um=jc.createUnmarshaller();
            
            URL url=new URL( targetUrl + URLEncoder.encode(ss, “UTF-8”) );
            
            Rss rss = (Rss)um.unmarshal(url);
            list = rss.getChannel().getItem();        
            
        }catch(Exception e){
            System.out.println(“newsListData error: “);
            e.printStackTrace();
        }
        
        return list;
    }
}