본문 바로가기

JAVA/Spring

[Spring] 공공데이터 api xml 데이터 파싱하기

참고 자료

 

JDOM 라이브러리 불러오기

implementation 'org.jdom:jdom2:2.0.6'

 

공공데이터 xml 불러오기

일단 xml 데이터 형식을 보기 위해 레스트 컨트롤러에서 공공데이터를 날것으로 불러와본다. 여기서 produce 형식을 XML로 설정해야 XML 문서가  형식에 맞춰 제대로 출력된다. 본인은 테스트를 위해 경기도 버스 노선 api를 불러왔다.

@RestController
@RequestMapping("/samplerest")
@Log4j2
@RequiredArgsConstructor
public class SampleRestController {

	@GetMapping(value = "/apitest", produces = MediaType.APPLICATION_XML_VALUE)
	public String callapihttp() throws Exception {
        StringBuilder urlBuilder = new StringBuilder("http://apis.data.go.kr/6410000/busrouteservice/getBusRouteInfoItem"); /*URL*/
        urlBuilder.append("?" + URLEncoder.encode("serviceKey","UTF-8") + "=본인이 받은 서비스키"); /*Service Key*/
        urlBuilder.append("&" + URLEncoder.encode("routeId","UTF-8") + "=" + URLEncoder.encode("200000085", "UTF-8")); /*노선ID*/
        URL url = new URL(urlBuilder.toString());
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod("GET");
        conn.setRequestProperty("Content-type", "application/xml");
        System.out.println("Response code: " + conn.getResponseCode());
        BufferedReader rd;
        if(conn.getResponseCode() >= 200 && conn.getResponseCode() <= 300) {
            rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
        } else {
            rd = new BufferedReader(new InputStreamReader(conn.getErrorStream()));
        }
        StringBuilder sb = new StringBuilder();
        String line;
        while ((line = rd.readLine()) != null) {
            sb.append(line);
        }
        rd.close();
        conn.disconnect();
        return sb.toString();

	}
}

해당 매핑 주소로 들어가보면 xml 문서가 뜬다.

 

JDOM라이브러리를 이용해 Java로 파싱하기

문서 형태가 어떤지 알았으니 일반 컨트롤러단에서 파싱을 해본다. (근데 보통 바로 컨트롤러단에서 파싱하나? 서비스에 넣고 DTO로 불러와도 될법한데..?🤔)

@Controller
@Log4j2
public class SampleController {

	@GetMapping("/sample")
	public void hello(Model model) {
		log.info("Sample Controller Test");
		model.addAttribute("msg", "HELLO WORLD");
	}
	
	@GetMapping("/sampleapi")
	public void sampleapi(Model model) throws Exception {
        StringBuilder urlBuilder = new StringBuilder("http://apis.data.go.kr/6410000/busrouteservice/getBusRouteInfoItem"); /*URL*/
        urlBuilder.append("?" + URLEncoder.encode("serviceKey","UTF-8") + "=본인이 받은 키값 입력"); /*Service Key*/
        urlBuilder.append("&" + URLEncoder	.encode("routeId","UTF-8") + "=" + URLEncoder.encode("200000085", "UTF-8")); /*노선ID*/
        URL url = new URL(urlBuilder.toString());
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod("GET");
        conn.setRequestProperty("Content-type", "application/xml");
        System.out.println("Response code: " + conn.getResponseCode());
        
        SAXBuilder builder = new SAXBuilder();
        String queryTime = "";
        Document document = builder.build(conn.getInputStream());
        Element root = document.getRootElement();
        List xmlelement = root.getChildren();
        Iterator it = xmlelement.iterator();
        
        List msgHeaderList = null;
        List msgBodyList = null;
        List busRouteInfoItemList = null;
	}
}

JDOM라이브러리에 있는 SAXBuider를 사용해 xml문서를 List 형태로 저장한다. 이를 이터레이터로 돌려 파싱만 하면 된다. 

 

이터레이터 돌리기

while(it.hasNext()) {
    Element e = (Element)it.next();
    System.out.println(e.getName());
    if(e.getName()=="msgHeader") {
        msgHeaderList = e.getChildren();
    }
    if(e.getName()=="msgBody") {
        msgBodyList = e.getChildren();
    }
}

System.out.println("<msgHeader>");
Iterator msgHeaderIt = msgHeaderList.iterator();
while(msgHeaderIt.hasNext()) {
    Element e = (Element)msgHeaderIt.next();
    System.out.println(e.getName()+" : "+e.getValue());
}

System.out.println("<msgBody>");
Iterator msgBodyIt = msgBodyList.iterator();
while(msgBodyIt.hasNext()) {
    Element e = (Element)msgBodyIt.next();
    System.out.println(e.getName()+" : "+e.getValue());
    if(e.getName()=="busRouteInfoItem") {
        busRouteInfoItemList = e.getChildren();
    }
}

System.out.println("<busRouteInfoItem>");
HashMap<String, String> resultMap = new HashMap<>();
Iterator busRouteInfoItemIt = busRouteInfoItemList.iterator();
while(busRouteInfoItemIt.hasNext()) {
    Element e = (Element)busRouteInfoItemIt.next();
    System.out.println(e.getName()+" : "+e.getValue());
    resultMap.put(e.getName(), e.getValue());
}

model.addAttribute("response", resultMap);

 

뷰단에 해시맵을 내보내면 아래와같이 나온다.

{upLastTime=22:10, peekAlloc=11, endStationName=한화꿈에그린, upFirstTime=04:50, companyName=수원여객, companyTel=031-244-5341, regionName=수원,화성, downFirstTime=06:20, routeTypeCd=13, routeName=98, companyId=4103100, downLastTime=23:35, routeId=200000085, districtCd=2, nPeekAlloc=15, endMobileNo=37707, endStationId=233001703, startMobileNo=1070, routeTypeName=일반형시내버스, startStationId=200000165, startStationName=이목동차고지.이목동입구}

 

대충 어떻게 파싱하는지 알았으니 apiVO를 따로 만들어 데이터를 고급스럽게 처리하자~

728x90