티스토리 뷰

 

이전에는 xml의 구성만 살펴보았다면 오늘은 이클립스에서 xml 파일을 불러와 출력하는 것을 해보았다.

 

 

 

먼저 url을 통해 xml 을 불러 오기 위해 url 을 조립한다.

StringBuilder를 사용해 외부 api의 url을 조립했다.

이전에 보았던 변수들과 분류 코드들을 참고하여 특정 값만 볼 수 있도록 &변수명=값 과 같은 형태로 append해준다.

그럼 파라미터가 url에 추가된다.

StringBuilder urlBuilder = new StringBuilder("https://apis.data.go.kr/B551182/hospInfoServicev2/getHospBasisList");
urlBuilder.append("?ServiceKey=인증key");
urlBuilder.append("&numOfRows=10");
urlBuilder.append("&dgsbjtCd=05");
urlBuilder.append("&page=" + page);
//이후 원하는 값이 있으면 해당 변수에 대한 것을 작성

 

 

 

API를 호출한다. HttpURLConnection을 사용해 조립한 url로 api에 요청을 보낸다.

응답 코드를 확인한 후 응답 스트림을 SAXBuilider를 사용해 xml 문서로 파싱해준다.

 

URL url = new URL(urlBuilder.toString());
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setRequestProperty("Content-Type", "application/xml");

SAXBuilder builder = new SAXBuilder();
Document document = builder.build(conn.getInputStream());
Element root = document.getRootElement();
List xmlelement = root.getChildren();
Iterator it = xmlelement.iterator();

 

 

정상적으로 파일을 가지고온다면 위와 같이 200번 코드가 발생하여 출력된다.

 

 

 

다음으로 XML 파싱을 한다.

JDOM 라이브러리를 사용해 xml 문서를 파싱한다.

xml 구성이 <header> <body> <items> 로 이루어져 있었기 때문에 아래와 같이 엘리먼트를 가져온다.

 

List<Element> headerList = null;
List<Element> bodyList = null;
List<Element> itemsList = null;

while (it.hasNext()) {
    Element e = (Element) it.next();
    if ("header".equals(e.getName())) {
        headerList = e.getChildren();
    }
    if ("body".equals(e.getName())) {
        bodyList = e.getChildren();
    }
    if ("items".equals(e.getName())) {
        itemsList = e.getChildren();
    }
}

 

 

 

다음으로 데이터를 추출한다.

 

헤더와 바디의 데이터를 추출하고 태그 안에 여러개가 존재할 수 있으므로 iterator 를 사용하여 반복 작업을 한다.

 System.out.println("<header>");
        Iterator headerIt = headerList.iterator();
        
        while(headerIt.hasNext()) {
        	Element e = (Element)headerIt.next();
        	System.out.println(e.getName()+" : "+e.getValue());
        	
        }
        
        System.out.println("<body>");
        Iterator bodyIt = bodyList.iterator();
        
        while(bodyIt.hasNext()) {
        	Element e = (Element)bodyIt.next();
        	System.out.println(e.getName()+" : "+e.getValue());
        	if(e.getName()=="items") {
        		itemsList = e.getChildren();
        	}
        }

 

 

 

<items> 아래 <item>에서 병원 정보를 추출하고 이것을 dataList에 저장했다.

<items>아래에는 여러개의 <item>이 존재하기 때문에 

Map<String, String> dataMap = new HashMap<>();을 통해 각 각의 <item> 요소마다 새로운 Map을 생성하도록 작성했다.

List<Map<String, String>> dataList = new ArrayList<>();
        System.out.println("<items>");
        Iterator itemsIt = itemsList.iterator();
        while (itemsIt.hasNext()) {
            Element e = (Element) itemsIt.next();
            System.out.println(e.getName() + " : " + e.getValue());

            if ("item".equals(e.getName())) {
                itemList = e.getChildren();
                Map<String, String> dataMap = new HashMap<>();  // 각각의 <item> 요소마다 새로운 Map을 생성
                for (Element itemElement : itemList) {
                    System.out.println(itemElement.getName() + " : " + itemElement.getValue());
                    dataMap.put(itemElement.getName(), itemElement.getValue());
                }
                dataList.add(dataMap);
            }
        }

 

 

 

 

이후 모델에 데이터를 전달하여 dataList를 model 객체에 저장하여 뷰로 전달했다.

int totalItemCount = Integer.parseInt(root.getChild("body")
        .getChild("totalCount")
        .getValue());
model.addAttribute("totalItemCount", totalItemCount);
model.addAttribute("dataList", dataList);

 

 

 

마지막으로 뷰 호출을 하여 이동했다.

return "/Hospital/index";

 

 

 

 

System.out.println으로 콘솔에 출력한 값들이다.

응답코드가 200으로 정상적으로 가지고 오는 것을 확인하고

Header 값과 body 값 그리고 items 값과 item 요소들을 출력한 것을 볼 수 있다.

 

 

 

 

 

뷰페이지는 아래와 같이 작성되었다.

dataMap에서 원하는 값들만 el을 사용하여 출력해주고 있는 코드이다.

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>    
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<!-- form 사용을 위한 선언 -->
    
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link href="<c:url value="/resources/css/bootstrap.min.css"/>"rel="stylesheet" />
<script src="${pageContext.request.contextPath }/resources/js/controllers.js"></script>
<!-- 스크립트 사용을 위해 선언 -->
<title>병원 정보</title>
</head>
<body>
    <h1>Result Page</h1>
    
	<c:forEach items="${dataList}" var="dataMap">
	    <div>
	   		<p>-----------------------------------</p>
	        <!-- 필요한 내용 출력 -->
	        <p>병원명 : ${dataMap.yadmNm }
	        <p>주소 : ${dataMap.addr}</p>
	        <p>병원종류 : ${dataMap.clCdNm}</p>
	        <p>전화번호 : ${dataMap.telno}</p>
	    </div>
	</c:forEach>

    <div>
        <!-- 페이지 전환을 위한 링크 -->
        <c:if test="${page > 1}">
            <a href="/sample?page=${page - 1}">이전 페이지</a>
        </c:if>
        
        <span>현재 페이지: ${page}</span>

		<c:if test="${page > 1}">
		    <a href="${pageContext.request.contextPath}/sample?page=${page - 1}">이전 페이지</a>
		</c:if>
		
		<c:if test="${page * 10 < totalItemCount}">
		    <a href="${pageContext.request.contextPath}/sample?page=${page + 1}">다음 페이지</a>
		</c:if>
    </div>
</body>
</html>

 

 

 

뷰 페이지로 이동한 후 출력된 값이다.

 

 

 

 

 

 

 

다시 또 생각해봐야할 점

1. 병원의 수가 약 12240개로 너무 방대하다. 이것을 줄일 필요가 있음 (의논 후 얼마나,어떤 기준으로 줄일 것인지 결정)

2. 수가 많은 만큼 api가 페이지로 나누어져있는데 페이지 호출에대한 문제가 있다. 

다음 누르면 2페이지의 정보들을 가져오도록 변경해주어야한다.

 

 

 

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday