현재 유지보수하고 있는 시스템에서 부동산통계정보시스템을 통해 데이터를 가져오고 있는데
해당 시스템의 아키텍쳐가 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으로 문제를 해결했지만
기왕 맞딱뜨린 문제였기에 이렇게 정리해본다. 이거 하나 하려고 추석에 블로그에 게시글만 엄청 쓴 느낌이 든다. 끝