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