245 lines
8.1 KiB
Java
245 lines
8.1 KiB
Java
package nlib.restful.service;
|
|
|
|
import java.io.ByteArrayInputStream;
|
|
import java.util.ArrayList;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
|
|
import javax.xml.stream.XMLEventReader;
|
|
import javax.xml.stream.XMLInputFactory;
|
|
import javax.xml.stream.XMLStreamException;
|
|
import javax.xml.stream.events.StartElement;
|
|
import javax.xml.stream.events.XMLEvent;
|
|
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
import com.fasterxml.jackson.databind.DeserializationFeature;
|
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
|
|
import nlib.util.StringUtil;
|
|
|
|
public class XmlConverter {
|
|
|
|
private static final Logger log = LoggerFactory.getLogger(XmlConverter.class);
|
|
|
|
public static HashMap<String, Object> convert(String xmlStr, String rootEleName) throws Exception {
|
|
|
|
if(xmlStr == null) return null;
|
|
|
|
ByteArrayInputStream bIn = new ByteArrayInputStream(xmlStr.getBytes());
|
|
HashMap<String, Object> resMap = new HashMap<String, Object>();
|
|
|
|
try {
|
|
XMLInputFactory inputFactory = XMLInputFactory.newInstance();
|
|
XMLEventReader eventReader = inputFactory.createXMLEventReader(bIn);
|
|
|
|
resMap = getElementValue(rootEleName, eventReader, null);
|
|
//log.debug("Converting XML to HashMap : Done >> " + resMap);
|
|
} catch (XMLStreamException e) {
|
|
log.error("convert XMLStreamException : " + e.toString());
|
|
} catch (Exception e) {
|
|
log.error("convert Error : " + e.toString());
|
|
}
|
|
|
|
return resMap;
|
|
}
|
|
|
|
/**
|
|
* @param rootElementName
|
|
* @param eventReader
|
|
* @param alreadyRootOpened : 부모 요소 찾기 없이 작업 진행할지 여부. false인 경우, rootElementName 요소를 찾아서 이후 값 추출 수행
|
|
* @param startElement
|
|
* @return
|
|
* @throws Exception
|
|
*/
|
|
public static HashMap<String, Object> getElementValue(
|
|
String rootElementName
|
|
, XMLEventReader eventReader
|
|
, XMLEvent firstChildElement) throws Exception {
|
|
|
|
HashMap<String, Object> retMap = new HashMap<String, Object>();
|
|
|
|
try {
|
|
|
|
int depth = (firstChildElement == null ? 0 : 1);
|
|
StartElement startElement = null;
|
|
|
|
XMLEvent event = firstChildElement;
|
|
|
|
String upperElementName = null;
|
|
String elementName = null; //(firstChildElement == null ? null : firstChildElement.asStartElement().getName().getLocalPart());
|
|
String content = null;
|
|
String elementValue = "";
|
|
HashMap<String, String> elementValues = null;
|
|
boolean hasSubElements = false;
|
|
boolean isFirst = true;
|
|
|
|
while (eventReader.hasNext()) {
|
|
|
|
// 이벤트가 함께 매개변수로 넘어온 경우, 처음 읽기 생략
|
|
if(!isFirst || event == null) {
|
|
event = eventReader.nextEvent();
|
|
}
|
|
|
|
if(isFirst) isFirst = false;
|
|
|
|
|
|
// 1 레벨 엘리먼트 찾기
|
|
if (depth == 0 && event.isStartElement() && event.asStartElement().getName().getLocalPart().equals(rootElementName)) {
|
|
depth++;
|
|
continue;
|
|
}
|
|
|
|
// 1 레벨 엘리먼트내의 2 레벨 엘리먼트 찾기
|
|
if(depth == 1 && elementName == null && event.isStartElement()) {
|
|
elementName = event.asStartElement().getName().getLocalPart();
|
|
elementValue = "";
|
|
elementValues = null;
|
|
hasSubElements = false;
|
|
depth++;
|
|
continue;
|
|
}
|
|
|
|
// 2 레벨 엘리먼트 내용 찾기
|
|
if(depth == 2 && elementName != null && event.isCharacters()) {
|
|
content = event.asCharacters().getData();
|
|
if(StringUtil.isNotEmpty(content)) {
|
|
elementValue += content;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
// 2 레벨 엘리먼트 종료
|
|
if(depth == 2 && elementName != null && event.isEndElement()) {
|
|
|
|
if(!elementName.equals(event.asEndElement().getName().getLocalPart())) {
|
|
throw new Exception("XML문의 요소 시작/종료 태그가 일치하지 않습니다. : " + elementName + " 요소가 " + event.asEndElement().getName().getLocalPart() + "로 종료되었습니다.");
|
|
}
|
|
|
|
addValue(retMap, elementName, elementValue);
|
|
//log.debug(elementName + " : -" + elementValue + "_");
|
|
|
|
elementName = null;
|
|
elementValue = "";
|
|
depth--;
|
|
}
|
|
|
|
// 2 레벨 엘리먼트 > 하위 엘리먼트 존재하는 경우
|
|
if(depth == 2 && elementName != null && event.isStartElement()) {
|
|
HashMap<String, Object> subMap = getElementValue(elementName, eventReader, event);
|
|
addValue(retMap, elementName, subMap);
|
|
depth--;
|
|
elementName = null;
|
|
}
|
|
|
|
// 1 레벨 엘리먼트 종료된 경우, 돌아가기
|
|
if(depth == 1 && elementName == null && event.isEndElement() && rootElementName.equals(event.asEndElement().getName().getLocalPart())) {
|
|
depth--;
|
|
return retMap;
|
|
}
|
|
|
|
} // while
|
|
|
|
} catch (XMLStreamException e) {
|
|
log.error("getElementValue Error : " + e.toString());
|
|
} catch (Exception e) {
|
|
log.error("getElementValue Error : " + e.toString());
|
|
}
|
|
|
|
return retMap;
|
|
}
|
|
|
|
public static void addValue(HashMap<String, Object> map, String key, Object value) throws Exception {
|
|
if(map == null) throw new Exception("값을 넣을 Map 변수가 초기화되지 않았습니다.");
|
|
|
|
if(key == null) return;
|
|
if(value == null) return;
|
|
|
|
Object curValObj = map.get(key);
|
|
if(curValObj == null) {
|
|
map.put(key, value);
|
|
return;
|
|
}
|
|
|
|
if(curValObj instanceof String || curValObj instanceof HashMap) {
|
|
List<Object> values = new ArrayList<Object>();
|
|
values.add(curValObj);
|
|
values.add(value);
|
|
map.put(key, values);
|
|
} else if(curValObj instanceof List) {
|
|
((ArrayList<Object>)curValObj).add(value);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
public static Object convertMapToObject(HashMap<String, String> map, Class voClass) {
|
|
final ObjectMapper mapper = new ObjectMapper(); // jackson's objectmapper
|
|
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
|
|
final Object voObj = mapper.convertValue(map, voClass);
|
|
return voObj;
|
|
}
|
|
|
|
/*
|
|
public static void main(String argv[]) throws Exception {
|
|
|
|
XmlConverter xmlConverter = new XmlConverter();
|
|
String xmlStr = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\r\n" +
|
|
"<!-- uac.service.board.qna_GET.xml -->\r\n" +
|
|
"<result>\r\n" +
|
|
" <code>S</code>\r\n" +
|
|
" <message>성공적으로 조회되었습니다.</message>\r\n" +
|
|
" <records>10</records>\r\n" +
|
|
" <page>1</page>\r\n" +
|
|
" <totPages>15</totPages>\r\n" +
|
|
" <record>\r\n" +
|
|
" <noticeNo>1</noticeNo>\r\n" +
|
|
" <noticeType>101</noticeType>\r\n" +
|
|
" <title>공지사항 테스트</title>\r\n" +
|
|
" <readCount>15</readCount>\r\n" +
|
|
" <regDate>2021-07-19</regDate>\r\n" +
|
|
" </record>\r\n" +
|
|
" <record>\r\n" +
|
|
" <noticeNo>2</noticeNo>\r\n" +
|
|
" <noticeType>101</noticeType>\r\n" +
|
|
" <title>공지사항 테스트</title>\r\n" +
|
|
" <readCount>55</readCount>\r\n" +
|
|
" <regDate>2021-07-19</regDate>\r\n" +
|
|
" </record>\r\n" +
|
|
" <record>\r\n" +
|
|
" <noticeNo>3</noticeNo>\r\n" +
|
|
" <noticeType>101</noticeType>\r\n" +
|
|
" <title>공지사항 테스트</title>\r\n" +
|
|
" <readCount>55</readCount>\r\n" +
|
|
" <regDate>2021-07-19</regDate>\r\n" +
|
|
" </record>\r\n" +
|
|
" <record>\r\n" +
|
|
" <noticeNo>4</noticeNo>\r\n" +
|
|
" <noticeType>101</noticeType>\r\n" +
|
|
" <title>공지사항 테스트</title>\r\n" +
|
|
" <readCount>55</readCount>\r\n" +
|
|
" <regDate>2021-07-19</regDate>\r\n" +
|
|
" </record>\r\n" +
|
|
" <record>\r\n" +
|
|
" <noticeNo>5</noticeNo>\r\n" +
|
|
" <noticeType>101</noticeType>\r\n" +
|
|
" <title>공지사항 테스트</title>\r\n" +
|
|
" <readCount>55</readCount>\r\n" +
|
|
" <regDate>2021-07-19</regDate>\r\n" +
|
|
" </record>\r\n" +
|
|
" <record>\r\n" +
|
|
" <noticeNo>6</noticeNo>\r\n" +
|
|
" <noticeType>101</noticeType>\r\n" +
|
|
" <title>공지사항 테스트</title>\r\n" +
|
|
" <readCount>55</readCount>\r\n" +
|
|
" <regDate>2021-07-19</regDate>\r\n" +
|
|
" </record>\r\n" +
|
|
" <end>3333</end>\r\n" +
|
|
"</result>";
|
|
|
|
HashMap<String, Object> resMap = xmlConverter.convert(xmlStr);
|
|
}
|
|
*/
|
|
}
|