1. 程式人生 > >將xml檔案物件轉化為Map物件

將xml檔案物件轉化為Map物件

一、基本思路

先將xml檔案轉化為document物件,並獲取到根節點,然後依次遍歷二級節點

如果二級節點擁有子節點的話:進入遞迴

如果二級節點沒有子節點的話:將資料封裝在本層Map 中

如果二級節點部分擁有子節點,部分沒有子節點,那麼進行特殊處理。

二、具體程式碼

package xmlToPojo;

import java.io.File;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.junit.Test;

public class xmlToCsdn {
	@Test
	public void main() {
		String filepath = "F:/WH000413.xml";
		Map map = mainMethod(filepath);
	}

	public Map mainMethod(String filepath) {
		Map<String, Object> map_finall = new LinkedHashMap<String, Object>();
		try {
			File file = new File(filepath);
			// 讀取xml檔案,封裝為doc物件
			SAXReader saxreader = new SAXReader();
			Document doc = saxreader.read(file);
			Element rootElement = doc.getRootElement();
			// 呼叫遞迴方法
			map_finall.put(rootElement.getName(), DiGui(rootElement));
		} catch (DocumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return map_finall;
	}

	public Map DiGui(Element rootElement) {
		// 對節點進行判斷
		int flag = hasGradeChrid(rootElement);
		// 儲存本層的map,採用LinkedHashMap,保證的順序
		Map<String, Object> map_this = new LinkedHashMap<String, Object>();
		// 儲存子節點的map,採用LinkedHashMap,保證的順序
		Map<String, Object> map_children = new LinkedHashMap<String, Object>();
		// 獲取節點迭代器
		Iterator<Element> iterator = rootElement.elementIterator();
		if (flag == 0) {// 說明該節點所有子節點均有子節點,進入遞迴
			int num = 0;
			while (iterator.hasNext()) {// 依次繼續對節點進行操作
				Element childelement = iterator.next();
				map_children = DiGui(childelement);
				map_this.put(childelement.getName() + "_" + num, map_children);
				num++;
			}
		}
		if (flag == 1) {// 說明該節點的所有子節點均無子節點,封裝資料
			while (iterator.hasNext()) {
				Element childelement = iterator.next();
				map_this.put(childelement.getName(),
						(String) childelement.getData());
			}
		}
		if (flag == 2) {// 說明了該節點的子節點有些擁有子節點,有些不擁有
			int nodes = rootElement.elements().size();// 獲取子節點個數
			while (nodes >= 1) {
				nodes--;
				int num = 0;//為了讓迴圈重複的節點,避免了key的衝突
				Element element = iterator.next();
				flag = hasGradeChrid(element);//對節點進行判斷
				if (flag == 1) {                          //對於子節點,如果只是普通的子節點,那麼直接將數進行封裝
					// 封裝如map,String,String
					map_this.put(element.getName(), element.getData());
				}
				else{                                     //非普通子節點,那麼進行遞迴
					map_children = DiGui(element);
					map_this.put(element.getName() + "_" + num, map_children);//為了讓迴圈重複的節點,避免了key的衝突
				}
			}
		}
		return map_this;
	}

	/**
	 * 用於判斷該節點的型別 0:說明該節點所有子節點均有子節點 1:說明該節點的所有子節點均無子節點 2:說明了該節點的子節點有些擁有子節點,有些不擁有
	 * 
	 * @param rootelement
	 * @return
	 */
	public int hasGradeChrid(Element rootelement) {
		int flag = 1;// 初始為1,用與處理對沒有子節點的節點進行判斷
		StringBuffer flag_arr = new StringBuffer();
		Iterator<Element> iterator = rootelement.elementIterator();
		while (iterator.hasNext()) {
			Element element = iterator.next();// 獲取入參rootelement節點的子節點
			// Iterator<Element> iterator_chirld = element.elementIterator();
			if (element.elements().size() > 0) {// 判斷是否有子節點
				flag_arr.append("0");
			} else {
				flag_arr.append("1");
			}
		}
		// 如果只包含0,說明該節點所有子節點均有子節點
		if (flag_arr.toString().contains("0")) {
			flag = 0;
		}
		// 如果只包含1,說明該節點的所有子節點均無子節點
		if (flag_arr.toString().contains("1")) {
			flag = 1;
		}
		// 如果同時包含了,0,1,說明了該節點的子節點有些擁有子節點,有些不擁有
		if (flag_arr.toString().contains("0")
				&& flag_arr.toString().contains("1")) {
			flag = 2;
		}
		return flag;
	}
}

三、測試例子

<?xml version="1.0" encoding="UTF-8"?>
<!--用XMLSpy v2012產生的 XML檔案(http://www.altova.com)-->
<WH000413 xsi:noNamespaceSchemaLocation="com.test.test" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
	<Head>
		<SendTime><![CDATA[20180822112506]]></SendTime>
		<FunctionCode><![CDATA[4346]]></FunctionCode>
		<SignerInfo><![CDATA[45]]></SignerInfo>
		<Version><![CDATA[1.0]]></Version>		
	</Head>
	<Declaration>
		<ReturnHead>
			<ApplyID><![CDATA[5C8610D]]></ApplyID>
			<No><![CDATA[20180727155013]]></No>
			<ProType><![CDATA[1]]></ProType>
			<ProID><![CDATA[de]]></ProID>
			<ProName><![CDATA[eee]]></ProName>
			<ProINFO><![CDATA[傳送成功]]></ProINFO>
		</ReturnHead>
		<ReturnDetail>
			<ListInfo>
				<USD><![CDATA[122.0545]]></USD>
				<Sum><![CDATA[29.7694]]></Sum>
				<Currency><![CDATA[JJJ]]></Currency>
				<Infos>
					<Info>
						<Qty><![CDATA[0]]></Qty>
						<Unit><![CDATA[Unit1]]></Unit>
						<UnPrice><![CDATA[0.5989]]></UnPrice>
					</Info>
					<Info>
						<Qty><![CDATA[0]]></Qty>
						<Unit><![CDATA[Unit2]]></Unit>
						<UnPrice><![CDATA[0.2030]]></UnPrice>
					</Info>
				</Infos>
			</ListInfo>
		</ReturnDetail>
	</Declaration>
</WH000413>

四、結果

{WH000413={Head_0={SendTime=20180822112506, FunctionCode=4346, SignerInfo=45, Version=1.0}, Declaration_1={ReturnHead_0={ApplyID=5C8610D, No=20180727155013, ProType=1, ProID=de, ProName=eee, ProINFO=傳送成功}, ReturnDetail_1={ListInfo_0={USD=122.0545, Sum=29.7694, Currency=JJJ, Infos_0={Info_0={Qty=0, Unit=Unit1, UnPrice=0.5989}, Info_1={Qty=0, Unit=Unit2, UnPrice=0.2030}}}}}}}

五、小結

其實邏輯也比較簡單,只是有時要根據xml報文的情況進行適當的修改。不過也基本離不開"本層資料本層封裝,若有子節點往下鑽"的基本思路。