將xml檔案物件轉化為Map物件
阿新 • • 發佈:2019-02-16
一、基本思路
先將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報文的情況進行適當的修改。不過也基本離不開"本層資料本層封裝,若有子節點往下鑽"的基本思路。