본문 바로가기
프로그래밍/Java-자주쓰는예제

【Java-데이터】 객체를 XML데이터로 변환하기

by 코이킹 2021. 9. 19.
반응형

1. 설명 

이 포스트에서 다룰 예제는 "데이터가 담기는 클래스의 객체 데이터를 XML로 변환"해주는 코드입니다.

신규 개발 안건의 경우 대부분 API 통신 데이터의 표준으로 JSON을 사용하는 경우가 많지만, 
오래전에 개발된 API의 통신 데이터의 표준은 XML데이터로 된 경우가 존재합니다. 

따라서 XML을 Object로, Object를 XML로 변환해 두는 방법을 익혀두면 언젠간 실무에서 도움이 될것 이라고 생각합니다. 

예제는  jackson-dataformat-xml과 jdom 라이브러리를 사용해서 구현했습니다. 
Jackson 라이브러리의 jackson-dataformat-xml으로 XML을 다루는게 더 편리했지만
제가 원하는 결과가 나오지 않았기에 jdom을 선택하게 되었습니다.


- XML로 변환할 클래스

public class Item {

	private int itemId;
	private String itemName;
	private int itemPrice;
	private boolean sales;
	private List<String> images;
	private List<StockHistory> stockHistories;
	private String joinDate;
    
   // ... Getter & Setter   
}


- 기대 값 XML 

<?xml version="1.0" encoding="UTF-8"?>
	<item>
		<itemId>1</itemId>
		<itemName>testItem1</itemName>
		<itemPrice>1000</itemPrice>
		<sales>true</sales>
		<images>
			<image>testItem1-img1.png</image>
			<image>testItem1-img2.png</image>
			<image>testItem1-img3.png</image>
		</images>
		<stockHistories>
			<stockHistory>
				<stockHistoryNo>1</stockHistoryNo>
				<count>2</count>
				<receivingDate>2021-09-19</receivingDate>
			</stockHistory>
			<stockHistory>
				<stockHistoryNo>2</stockHistoryNo>
				<count>4</count>
				<receivingDate>2021-09-19</receivingDate>
			</stockHistory>
			<stockHistory>
				<stockHistoryNo>3</stockHistoryNo>
				<count>6</count>
				<receivingDate>2021-09-19</receivingDate>
			</stockHistory>
		</stockHistories>
		<joinDate>2021-09-19</joinDate>
	</item>


- jackson-dataformat-xml으로 XML변환의 경우 

<Item>
	<itemId>1</itemId>
	<itemName>testItem1</itemName>
	<itemPrice>1000</itemPrice>
	<sales>true</sales>
	<images>
		<images>testItem1-img1.png</images>
		<images>testItem1-img2.png</images>
		<images>testItem1-img3.png</images>
	</images>
	<stockHistories>
		<stockHistories>
			<stockHistoryNo>1</stockHistoryNo>
			<count>2</count>
			<receivingDate>2021-09-19</receivingDate>
		</stockHistories>
		<stockHistories>
			<stockHistoryNo>2</stockHistoryNo>
			<count>4</count>
			<receivingDate>2021-09-19</receivingDate>
		</stockHistories>
		<stockHistories>
			<stockHistoryNo>3</stockHistoryNo>
			<count>6</count>
			<receivingDate>2021-09-19</receivingDate>
		</stockHistories>
	</stockHistories>
	<joinDate>2021-09-19</joinDate>
</Item>

 

기대값이 다르다고 한 부분은 images 태그입니다. 저는 images의 하위에 imgae태그를 넣는 배열 형태의 구조로 데이터를 변환하고 싶었지만, 
 jackson-dataformat-xml를 사용해서 XML변환을 한 결과 images태그가 여러개 출력된 것을 확인할 수 있습니다. 

 

2. 소스코드

- 메서드 

public interface XmlConverter {

	public String objToXml(Object obj);
	public Element makeXmlElement(Object element);
}

public class XmlConverterItem implements XmlConverter {

	@Override
	public String objToXml(Object obj) {
		if (obj == null || !(obj instanceof Item)) return null;
		Item item = (Item) obj;
		Element rootEl = new Element("root");
		this.doc = new Document(rootEl);
		
		Element itemContents = makeItemXml(item);
		this.doc.getRootElement().addContent(itemContents);
		
		fm.setEncoding("UTF-8");
		XMLOutputter output = new XMLOutputter(fm);
		return output.outputString(doc);
	}
	
	@Override
	public Element makeXmlElement(Object element) {
		Item item = (Item) element;
		
		Element itemContents = new Element("item");
		itemContents.addContent(new Element("itemId").addContent(String.valueOf(item.getItemId())));
		itemContents.addContent(new Element("itemName").addContent(item.getItemName()));
		itemContents.addContent(new Element("itemPrice").addContent(String.valueOf(item.getItemPrice())));
		itemContents.addContent(new Element("sales").addContent(String.valueOf(item.isSales())));
		
		Element imagesContents = new Element("images");
		for (String image : item.getImages()) {
			Element imageContents = new Element("image");
			imageContents.addContent(image);
			imagesContents.addContent(imageContents);
		}
		itemContents.addContent(imagesContents);
		
		Element historiesContents = new Element("stockHistories");
		for (StockHistory stock : item.getStockHistories()) {
			Element stockHistoryContents = new Element("stockHistory");
			stockHistoryContents.addContent(new Element("stockHistoryNo").addContent(String.valueOf(stock.getStockHistoryNo())));
			stockHistoryContents.addContent(new Element("count").addContent(String.valueOf(stock.getCount())));
			stockHistoryContents.addContent(new Element("receivingDate").addContent(String.valueOf(stock.getReceivingDate())));
			historiesContents.addContent(stockHistoryContents);
		}
		itemContents.addContent(historiesContents);
		itemContents.addContent(new Element("joinDate").addContent(item.getJoinDate()));
		
		return itemContents;
	}
}

XML로 변환하고자하는 Java 클래스가 다수 존재하고, XML로 데이터를 변환시의 성형과정은 다를 것이라 가정했습니다. 

따라서 데이터를 성형해서 출력하는 기능을 인터페이스에 정의하고,  출력하고자하는 Java 클래스에 맞게 인터페이스에 정의한 기능을 구현했습니다. 

 

Document객체가 출력할 XML문서에 해당합니다. 

이 Document객체에 Element객체를 붙여나가는 형식으로 원하는 XML의 형태를 성형하여 출력하게 됩니다.  

 

public class XmlConverterItemList extends XmlConverterItem {

	@Override
	public String objToXml(Object obj) {
		if (obj == null) return null;
		
		List<Item> itemList = (List<Item>)obj;
		Element rootEl = new Element("root");
		this.doc = new Document(rootEl);
		
		Element itemsContents = new Element("items");
		for (Item item : itemList) {
			itemsContents.addContent(makeXmlElement(item));
		}
		this.doc.getRootElement().addContent(itemsContents);
		
		fm.setEncoding("UTF-8");
		XMLOutputter output = new XMLOutputter(fm);
		return output.outputString(doc);
	}
}

객체의 리스트를 XML로 출력하기위해서 객체 하나를 XML로 변환하기위한 클래스(XmlConverterItem)를 상속하여 기능을 구현했습니다. 

Item객체를 Element로 만드는 기능은 XmlConverterItem에서 이미 구현했으므로 그대로 활용하면 됩니다. 

 

	public String ObjToXml(Object obj) {
		if (obj == null) return null;
		
		String res = null;
		
		try {
			res = this.xmlConverter.objToXml(obj);
		} catch (Exception e) { e.printStackTrace(); }
		
		return res;
	}

유틸클래스에서 메서드를 정의하여 유틸클래스에서 기능을 불러올 수 있도록 합니다.  

 

- 메인

public class Data_03_XmlMake {
	static SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); 
	static XmlUtil xu = XmlUtil.getInstance();
	static FileUtil fu = FileUtil.getInstance();
	
	public static void main(String[] args) {
		try {
			for (String str : args ) {
				System.out.println("Param : "+str);
			}

			/**
			 * Object -> XML , XmlMapper 사용의 경우 
			 */
			Item item1 = getItem(1);
			File itemTestMapperFile = xu.ObjToXmlUseMapper(item1, args[0]);
			System.out.println("(1) Object -> XML Use XmlMapper : "+ fu.readPerLine(itemTestMapperFile));
			System.out.println("");
			
			
			/**
			 * Object -> XML
			 */
			xu.setObjToXml(new XmlConverterItem());
			Item item2 = getItem(1);
			File xmlText02 = xu.ObjToXml(item2, args[1]);
			System.out.println("(2) Object -> XML : "+ fu.readPerLine(xmlText02));
			System.out.println("");
			
			
			/**
			 * List<Object> -> XML List
			 */
			List<Item> items = getItems();
			File itemListTestMapperFile = xu.ObjToXmlUseMapper(items, args[2]);
			System.out.println("(3) List<Object> -> XML List Use XmlMapper : "+ fu.readPerLine(itemListTestMapperFile));
			System.out.println("");
			
			
			xu.setObjToXml(new XmlConverterItemList());
			xu.ObjToXml(items, args[3]);
			System.out.println("(4) List<Object> -> XML List : "+ fu.readPerLine(new File(args[3])));
			
			
			System.exit(0);
			
		} catch (Exception e) {
			e.printStackTrace();
			System.exit(1);
		}
	}
  }


3. 실행결과【Windows(이클립스) / Linux】

이클립스에서 실행결과
Xml Mapper를 사용하여 XML 변환
jdom을 사용하여 XML변환
Xml Mapper를 사용하여 객체 리스트를 XML로 변환
jdom을 사용하여 객체리스트를 XML로 변환


4. 전체코드

https://github.com/leeyoungseung/template-java

반응형

댓글