개발공작소
article thumbnail
728x90

 

 

 

 

공공데이터포털 API를 통해 데이터를 가져오면 보통 JSON/XML 형식으로 가져오는데 ( 요즘은 JSON을 많이 쓰지만.. )

XML로 데이터를 가져오는 경우, 원하는 태그의 데이터를 추출하는 방법을 정리하려고 한다.

 

해당글에서는 2가지 방법을 소개하려고 한다.

 

1) 특정태그의 데이터를 1개 가져오는 방법

2) 특정태그의 데이터를 여러개 가져오는 방법

 

틀린 게 있을 수도 있지만, 그냥 정리하는 겸 쓴 글이기도 하고 어떤 사람들에게는 도움이 될 수도 있다고 생각한다.

 

우선 샘플로 사용 할 데이터는 공공데이터포털에서 제공하는 기상청_지상(종관, ASOS) 일자료 조회서비스이다.

자세한 내용을 보고싶은 사람은 아래 링크를 통해 이동하여 확인하도록 하자.

 

기상청_지상(종관, ASOS) 일자료 조회서비스로 이동

 

 

 

샘플URL ( 기상청_지상(종관, ASOS) 일자료 조회서비스 Doc에서 제공 )

http://apis.data.go.kr/1360000/AsosDalyInfoService/getWthrDataList
?serviceKey=인증키&numOfRows=10&pageNo=1
&dataCd=ASOS&dateCd=DAY&startDt=20100101&endDt=20100102&stnIds=108

위의 URL에 본인의 인증키를 그대로 넣고 주소창에 치면 데이터를 확인할 수 있다. 나는 이걸 사용 할 예정이다.

 

위의 URL을 통해 실제 가져온 데이터

 

 

 

XML데이터에서 원하는 태그의 데이터를 가져오는 방법

 

1. xPath를 통해 XML태그의 데이터를 가져오는 방법

 

샘플코드

package app.model.com;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Document;
import org.xml.sax.SAXException;

public class XmlExample {

	public static void main(String[] args) throws IOException, SAXException, ParserConfigurationException, XPathExpressionException {
            /**
             * testUrl : 공공데이터포털 기상청_지상(종관, ASOS) 일자료 조회서비스 샘플 URL
             * result : 받아온 데이터(XML)를 문자열로 받을 변수
             * line : 받아온 데이터값을 읽을 변수
             */
            String testUrl = "http://apis.data.go.kr/1360000/AsosDalyInfoService/getWthrDataList?serviceKey=인증키&pageNo=1&numOfRows=10&dataType=XML&dataCd=ASOS&dateCd=DAY&startDt=20210101&endDt=20220601&stnIds=108";
            String result = "";
            String line = "";

            /**
             * URL 생성 및 openStream()를 통해 서버통신
             * bf에 공공데이터포털에서 받아온 데이터를 적재
             * bf에서 데이터를 읽어들여 값이 null이 될때까지 반복하여
             * line을 result에 concat해줌 
             */
            StringBuilder urlBuilder = new StringBuilder();

            urlBuilder.append(testUrl);
            URL url = new URL(urlBuilder.toString());

            BufferedReader bf;

            bf = new BufferedReader(new InputStreamReader(url.openStream()));

            while((line = bf.readLine())!=null) {
                	result = result.concat(line);
            }

            /**
             * 받아온 xml문자열인 result을 가지고 Document인 xml을 선언
             * xpath를 통해 원하는 태그의 데이터를 각 String변수에 담음
             * 여기서 데이터 태그에 맞는 자식노드를 작성해주어야함..
             * stnNm 라는 데이터를 가져오기 위해서는 //response//body//items//item//stnNm와 같이 작성
             */
            Document xml = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new ByteArrayInputStream(result.getBytes()));

            xml.getDocumentElement().normalize();
            XPath xpath = XPathFactory.newInstance().newXPath();
            String stnNm = (String)xpath.evaluate("//response//body//items//item//stnNm", xml, XPathConstants.STRING);
            String tm = (String)xpath.evaluate("//response//body//items//item//tm", xml, XPathConstants.STRING);
            String maxTaHrmt = (String)xpath.evaluate("//response//body//items//item//maxTaHrmt", xml, XPathConstants.STRING);

            /**
             * 받아온 데이터를 출력함
             */
            System.out.println(stnNm);
            System.out.println(tm);
            System.out.println(maxTaHrmt);

        }

}

 

 

결과화면

 

근데 이렇게 xpath를 통해 데이터를 String에 넣으면 데이터를 하나씩밖에 못가져온다..

보통 우리가 데이터를 가져올 때, 몇백건이든 몇천건이든 많은 데이터를 가져오는데.. 그렇게 가져오려면

아래와 같이 반복문을 통해 nodeList에서 각 데이터를 추출하고 넣어줘야 한다.

 

 

 

2. 여러개의 태그 데이터를 가져오는 방법

 

샘플코드

package app.model.com;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class XmlExample {

	public static void main(String[] args) throws IOException, SAXException, ParserConfigurationException, XPathExpressionException {
            /**
             * testUrl : 공공데이터포털 기상청_지상(종관, ASOS) 일자료 조회서비스 샘플 URL
             * result : 받아온 데이터(XML)를 문자열로 받을 변수
             * line : 받아온 데이터값을 읽을 변수
             * xmlMap : 추출한 문자열을 담을 Map
             * resultList : xmlMap을 담을 List
             */
            String testUrl = "http://apis.data.go.kr/1360000/AsosDalyInfoService/getWthrDataList?serviceKey=인증키&pageNo=1&numOfRows=10&dataType=XML&dataCd=ASOS&dateCd=DAY&startDt=20210101&endDt=20220601&stnIds=108";
            String result = "";
            String line = "";

            HashMap<String, String> xmlMap = new HashMap<String, String>();
            ArrayList<Map<String, String>> resultList = new ArrayList<Map<String, String>>();

            /**
             * URL 생성 및 openStream()를 통해 서버통신
             * bf에 공공데이터포털에서 받아온 데이터를 적재
             * bf에서 데이터를 읽어들여 값이 null이 될때까지 반복하여
             * line을 result에 concat해줌 
             */
            StringBuilder urlBuilder = new StringBuilder();

            urlBuilder.append(testUrl);
            URL url = new URL(urlBuilder.toString());
            BufferedReader bf;

            bf = new BufferedReader(new InputStreamReader(url.openStream()));

            while((line = bf.readLine())!=null) {
                result = result.concat(line);
            }

            /**
             * 받아온 xml문자열인 result을 가지고 Document인 xml을 선언
             * xpath의 경로는 자신이 가져올 데이터들을 포함하는 태그임
             * 실제 XML트리를 보면서 이해하면 될 것 같음
             */
            Document xml = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new ByteArrayInputStream(result.getBytes()));

            xml.getDocumentElement().normalize();
            XPath xpath = XPathFactory.newInstance().newXPath();
            NodeList nodeList = (NodeList) xpath.evaluate("//response//body//items//item", xml, XPathConstants.NODESET); 

            /**
             * item태그에서 원하는 데이터 3가지를 지정함
             * 1) stnNm : 지점명
             * 2) tm : 시간
             * 3) maxTaHrmt : 최저기온 시각
             */
            String stnNm = "";
            String tm = "";
            String maxTaHrmt = "";

            /**
             * nodeList의 길이만큼 반복문을 돌림. ( 10개의 item이 있을 경우, 10회 반복.. )
             * 각 node를 Element객체인 eElement로 선언
             * getElementsByTagName()를 통해 원하는 태그 값의 0번째 값을 getTextContent()로
             * Stirng 문자열로 추출하여 각 String 변수에 적재함
             * getElementsByTagName() 안의 파라메터는 실제 XML트리의 item태그 안의 태그를 의미함..
             * 이해 안되면 직접 XML트리를 보면서 테스트 해보면 될 듯 함..
             */
            for (int index = 0; index < nodeList.getLength(); index++) {

                    Element eElement = (Element) nodeList.item(index);

                    /**xmlMap 생성자 초기화*/
                    xmlMap = new HashMap<String, String>();
                    /**각 값을 적재*/
                    stnNm = eElement.getElementsByTagName("stnNm").item(0).getTextContent();
                    tm = eElement.getElementsByTagName("tm").item(0).getTextContent();
                    maxTaHrmt = eElement.getElementsByTagName("maxTaHrmt").item(0).getTextContent();
                    /**가져온 값을 xmlMap에 put 해줌*/
                    xmlMap.put("stnNm", stnNm);
                    xmlMap.put("tm", tm);
                    xmlMap.put("maxTaHrmt", maxTaHrmt);
                    /**xmlMap을 List에 add해줌*/
                    resultList.add(xmlMap);
            }
            /**resultList를 콘솔에 출력해줌*/
            System.out.println(resultList);
        }

}

 

 

결과화면

 

 

이렇게 하면 <item>이라는 태그를 여러개 가져올 수 있다. 객체 형태로 배열에 담았으니,

필요한 곳에서 꺼내 쓰면 될 것 같다..

 

 

코드가 너무 길어져서 읽기 싫을 수도 있지만.. 막 어려운 코드는 아니니 필요한 사람들은 코드를 직접 디버깅 걸어서

하나하나 보면서 이해해보도록 하자..

 

 

 

 

 

728x90
profile

개발공작소

@모찌바라기

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!