개발공작소
article thumbnail
728x90

 

 

 

 

현재 유지보수하고 있는 시스템에서 부동산통계정보시스템을 통해 데이터를 가져오고 있는데

해당 시스템의 아키텍쳐가 6월 중에 변경이 되서 새로 개발해야 하는 상황이 생겼다.

 

기존에는 XML형식으로 가져오기도 했고, <Tag>로 가져오도록 개발이 되어 있었는데 아키텍쳐가 변경되면서

아래와 같이 XML데이터를 리턴하도록 변경되었다.

 

 

<results>
    <currentCount>5</currentCount>
    <data>
        <item>
            <col name="ALL_CNT">25014</col>
            <col name="DEAL_OBJ">01</col>
            <col name="LEVEL_NO">0</col>
            <col name="REGION_CD">11000</col>
            <col name="REGION_NM">서울</col>
            <col name="RESEARCH_DATE">202102</col>
        </item>
    </data>
</results>

 

대충 설명하자면, 기존에는 item태그안의 tag명으로 데이터를 구분하였는데 현재는 tag명이 'col'로 고정되어 있고

name 속성으로 데이터를 구분하게 변경 되었다.. 그래서 기존 코드를 사용하는 것이 불가능해진 상황..

( 결국 XML말고 JSON으로 받아오도록 변경해 개발했지만 XML로도 할 수 있는 방법이 있을 것 같아 공부함 )

 

 

tag명으로 데이터를 추출하는 방법은 아래 링크를 통해 확인하도록 하자

 

자바(JAVA) : XML데이터에서 원하는 태그(Tag)의 데이터값을 추출하는 방법

 

그래서 어떻게 하면 name 속성으로 각 item들의 데이터를 가져올 수 있을까 고민하다가 찾은 방법은 아래와 같다.

 

 

 

XML데이터에서 name속성으로 데이터를 추출하는 방법

 

 

실제 URL을 통해 가져오는 데이터 화면

보면 알겠지만 item태그 안의 값들의 태그가 전부 col이고, name 속성으로 구분하고 있다.

이제 저 name 속성의 값을 통해 원하는 데이터를 추출해보도록 하자

 

 

샘플코드

package app.model.com;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
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.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class XmlTest {

	public static void main(String[] args) throws UnsupportedEncodingException, IOException, SAXException, ParserConfigurationException, XPathExpressionException {

            String testURL = "https://api.odcloud.kr/api/HousePriceTrendSvc/v1/getHousePriceIndex?page=1&perPage=15&returnType=XML&cond[RESEARCH_DATE%3A%3ALTE]=202209&cond[RESEARCH_DATE%3A%3AGTE]=201401&cond[APT_TYPE%3A%3AEQ]=1&cond[TR_GBN%3A%3AEQ]=S&cond[WEEK_FLAG%3A%3AEQ]=M&serviceKey=인증키";
            String result = "";
            String line = "";

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

            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);
            }

            Document xml = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new ByteArrayInputStream(result.getBytes()));
            xml.getDocumentElement().normalize();
            XPath xPath1 = XPathFactory.newInstance().newXPath();
            /**
             * XML 트리구조에서 data/item을 nodeList에 담아줌. = 10개의 item이 있다면 nodeList의 길이는 10이 됨
             * item의 개수만큼 반복문을 돌리고 각 item을 node로 선언함
             * 각 item안의 childNodes를 NodeList로 선언함. 여기서 childNodes는 item안의 col 태그를 의미
             * col의 개수만큼 반복문을 수행하고, 각 col을 Node(childNode)로 선언함
             * childNode에서 getTextContent()함수로 value값을 추출함
             * Element에서 getAttribute 함수를 통해 name 속성의 value값을 추출함
             * 2가지 값을 xmlMap에 적재한 뒤, List에 add해줌
             */
            NodeList nodeList = (NodeList)xPath1.compile("//data/item").evaluate(xml, XPathConstants.NODESET);
                for (int index = 0; index < nodeList.getLength(); index++) {
                        Node node = nodeList.item(index);
                        NodeList cdList = node.getChildNodes();
                        xmlMap = new HashMap<String, String>();
                        for(int j = 0; j<cdList.getLength(); j++) {
                                Node childNode = cdList.item(j);
                                Element eElement = (Element) cdList.item(j);
                                String nameVal = eElement.getAttribute("name");
                                xmlMap.put(nameVal, childNode.getTextContent());
                        }
                        resultList.add(xmlMap);
                }

                for(int i=0; i< resultList.size(); i++) {
                    	System.out.println(resultList.get(i).get("REGION_NM") + ", " + resultList.get(i).get("REGION_CD") + ", " + resultList.get(i).get("REGION_CD"));
                }

        }

}

 

코드를 보면 위 링크와 비슷해서 세세한 설명을 주석으로 달지는 않았다.

nodeList를 통해 for문을 돌리는 저 부분이 핵심이기 때문에 주석을 달아놨다.

실제로 인증키를 발급 받은 뒤 실행하고 디버깅을 걸어서 확인해보도록 하자.

문제가 없다면 정상적으로 아래와 같이 출력이 될 것이다.

 

 

결과화면

 

 

구글링을 해봐도 방법이 마땅치 않아 스택오버 플로우나 이런 저런 곳에서 제시하는 해결방법들을

조금씩 섞어서 코드를 작성했다. 여기서는 name 속성을 사용했지만, id 같은 속성도 물론 이용 가능할 것 같다.

 

요즘은 XML에서 JSON으로 넘어가는 추세이기도 하고 결국 나도 JSON으로 문제를 해결했지만

기왕 맞딱뜨린 문제였기에 이렇게 정리해본다. 이거 하나 하려고 추석에 블로그에 게시글만 엄청 쓴 느낌이 든다. 끝

 

 

 

 

 

 

728x90
profile

개발공작소

@모찌바라기

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