Java读取多层级xml文件

た 入场券 2022-07-14 09:29 305阅读 0赞

最近在做国际客服北京职场的项目,需要提供一个接口服务端的能力,也就是需要开发一个http+xml的协议,入参和出参均为Map格式,各系统间的请求或应答是以xml格式封装的。在将返回报文(xml)解析为Map输出时遇到一个难点:Java对于多层级xml的解析。现以一个客户资料查询接口为例将解析过程记录如下:

返回xml报文的简化形式:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <ROOT>
  3. <HEAD>
  4. <ORIGIN_DOMAIN>kefuxitongbianma</ORIGIN_DOMAIN>
  5. <HOME_DOMAIN>CUGCRM</HOME_DOMAIN>
  6. <ACTION_CODE>1</ACTION_CODE>
  7. <BUSI_CODE>QUERYCUST</BUSI_CODE>
  8. <TRANS_ID>20160220160635123456</TRANS_ID>
  9. <RET_CODE>0000</RET_CODE>
  10. <RET_MSG>success</RET_MSG>
  11. </HEAD>
  12. <BODY>
  13. <TOTAL_RECORDS>20</TOTAL_RECORDS>
  14. <TOTAL_PAGE>10</TOTAL_PAGE>
  15. <CURRENT_PAGE>1</CURRENT_PAGE>
  16. <CUSTINFOLIST>
  17. <CUSTINFO>
  18. <CUST_TYPE>001</CUST_TYPE>
  19. <VIP_FLAG>true</VIP_FLAG>
  20. </CUSTINFO>
  21. <CUSTINFO>
  22. <CUST_TYPE>002</CUST_TYPE>
  23. <VIP_FLAG>false</VIP_FLAG>
  24. </CUSTINFO>
  25. <CUSTINFO>
  26. <CUST_TYPE>003</CUST_TYPE>
  27. <VIP_FLAG>false</VIP_FLAG>
  28. </CUSTINFO>
  29. </CUSTINFOLIST>
  30. </BODY>
  31. </ROOT>
  32. import java.util.ArrayList;
  33. import java.util.HashMap;
  34. import java.util.List;
  35. import java.util.Map;
  36. import java.util.Set;
  37. import net.sf.json.JSONObject;
  38. import org.apache.log4j.Logger;
  39. import org.dom4j.Document;
  40. import org.dom4j.DocumentException;
  41. import org.dom4j.DocumentHelper;
  42. import org.dom4j.Element;
  43. import org.dom4j.Namespace;
  44. import org.dom4j.QName;
  45. /**
  46. * 解析xml的工具类
  47. * 1、将多层级xml解析为Map
  48. * 2、将多层级xml解析为Json
  49. *
  50. * @author lmb
  51. *
  52. */
  53. public class ParseXmlUtil {
  54. public static Logger logger = Logger.getLogger(ParseXmlUtil.class);
  55. public static void main(String[] args) {
  56. // 获取一个xml文件
  57. String textFromFile = MyXmlUtil.XmlToString();
  58. //将xml解析为Map
  59. Map resultMap = xml2map(textFromFile);
  60. //将xml解析为Json
  61. String resultJson = xml2Json(textFromFile);
  62. }
  63. /**
  64. * 将xml格式响应报文解析为Json格式
  65. * @param responseXmlTemp
  66. * @return
  67. */
  68. public static String xml2Json(String responseXmlTemp) {
  69. Document doc = null;
  70. try {
  71. doc = DocumentHelper.parseText(responseXmlTemp);
  72. } catch (DocumentException e) {
  73. logger.error("parse text error : " + e);
  74. }
  75. Element rootElement = doc.getRootElement();
  76. Map<String,Object> mapXml = new HashMap<String,Object>();
  77. element2Map(mapXml,rootElement);
  78. String jsonXml = JSONObject.fromObject(mapXml).toString();
  79. System.out.println("Json >>> " + jsonXml);
  80. return jsonXml;
  81. }
  82. /**
  83. * 将xml格式响应报文解析为Map格式
  84. * @param responseXmlTemp
  85. * @param thirdXmlServiceBean
  86. * @return
  87. * @throws DocumentException
  88. */
  89. public static Map<String, Object> xml2map(String responseXmlTemp) {
  90. Document doc = null;
  91. try {
  92. doc = DocumentHelper.parseText(responseXmlTemp);
  93. } catch (DocumentException e) {
  94. logger.error("parse text error : " + e);
  95. }
  96. Element rootElement = doc.getRootElement();
  97. Map<String,Object> mapXml = new HashMap<String,Object>();
  98. element2Map(mapXml,rootElement);
  99. System.out.println("Map >>> " + mapXml);
  100. return mapXml;
  101. }
  102. /**
  103. * 使用递归调用将多层级xml转为map
  104. * @param map
  105. * @param rootElement
  106. */
  107. public static void element2Map(Map<String, Object> map, Element rootElement) {
  108. //获得当前节点的子节点
  109. List<Element> elements = rootElement.elements();
  110. if (elements.size() == 0) {
  111. //没有子节点说明当前节点是叶子节点,直接取值
  112. map.put(rootElement.getName(),rootElement.getText());
  113. }else if (elements.size() == 1) {
  114. //只有一个子节点说明不用考虑list的情况,继续递归
  115. Map<String,Object> tempMap = new HashMap<String,Object>();
  116. element2Map(tempMap,elements.get(0));
  117. map.put(rootElement.getName(),tempMap);
  118. }else {
  119. //多个子节点的话就要考虑list的情况了,特别是当多个子节点有名称相同的字段时
  120. Map<String,Object> tempMap = new HashMap<String,Object>();
  121. for (Element element : elements) {
  122. tempMap.put(element.getName(),null);
  123. }
  124. Set<String> keySet = tempMap.keySet();
  125. for (String string : keySet) {
  126. Namespace namespace = elements.get(0).getNamespace();
  127. List<Element> sameElements = rootElement.elements(new QName(string,namespace));
  128. //如果同名的数目大于1则表示要构建list
  129. if (sameElements.size() > 1) {
  130. List<Map> list = new ArrayList<Map>();
  131. for(Element element : sameElements){
  132. Map<String,Object> sameTempMap = new HashMap<String,Object>();
  133. element2Map(sameTempMap,element);
  134. list.add(sameTempMap);
  135. }
  136. map.put(string,list);
  137. }else {
  138. //同名的数量不大于1直接递归
  139. Map<String,Object> sameTempMap = new HashMap<String,Object>();
  140. element2Map(sameTempMap,sameElements.get(0));
  141. map.put(string,sameTempMap);
  142. }
  143. }
  144. }
  145. }
  146. }

xml文件读取工具类:

  1. import java.io.File;
  2. import java.io.IOException;
  3. import java.io.StringWriter;
  4. import org.jdom.Document;
  5. import org.jdom.input.SAXBuilder;
  6. import org.jdom.output.Format;
  7. import org.jdom.output.XMLOutputter;
  8. /**
  9. * 读取一个xml文件返回string
  10. * @author lmb
  11. *
  12. */
  13. public class MyXmlUtil {
  14. /**
  15. * 加载xml文件
  16. * @return Document
  17. */
  18. public static Document load(){
  19. Document document=null;
  20. String url="E://2.xml";
  21. try {
  22. SAXBuilder reader = new SAXBuilder();
  23. document=reader.build(new File(url));
  24. } catch (Exception e) {
  25. e.printStackTrace();
  26. }
  27. return document;
  28. }
  29. /**
  30. * 将xml文件转换为String串
  31. * @return
  32. */
  33. public static String XmlToString(){
  34. Document document=null;
  35. document=load();
  36. Format format =Format.getPrettyFormat();
  37. format.setEncoding("UTF-8");//设置编码格式
  38. StringWriter out=null; //输出对象
  39. String sReturn =""; //输出字符串
  40. XMLOutputter outputter =new XMLOutputter();
  41. out=new StringWriter();
  42. try {
  43. outputter.output(document,out);
  44. } catch (IOException e) {
  45. e.printStackTrace();
  46. }
  47. sReturn=out.toString();
  48. return sReturn;
  49. }
  50. }

控制台打印结果:

  1. Map >>> {BODY={TOTAL_RECORDS={TOTAL_RECORDS=20}, CUSTINFOLIST={CUSTINFO=[{CUST_TYPE={CUST_TYPE=001}, VIP_FLAG={VIP_FLAG=true}}, {CUST_TYPE={CUST_TYPE=002}, VIP_FLAG={VIP_FLAG=false}}, {CUST_TYPE={CUST_TYPE=003}, VIP_FLAG={VIP_FLAG=false}}]}, TOTAL_PAGE={TOTAL_PAGE=10}, CURRENT_PAGE={CURRENT_PAGE=1}}, HEAD={ACTION_CODE={ACTION_CODE=1}, ORIGIN_DOMAIN={ORIGIN_DOMAIN=kefuxit}, BUSI_CODE={BUSI_CODE=QUERYCUST}, HOME_DOMAIN={HOME_DOMAIN=CUGCRM}, TRANS_ID={TRANS_ID=20160220160635123456}, RET_MSG={RET_MSG=success}, RET_CODE={RET_CODE=0000}}}
  2. Json >>> {"BODY":{"TOTAL_RECORDS":{"TOTAL_RECORDS":"20"},"CUSTINFOLIST":{"CUSTINFO":[{"CUST_TYPE":{"CUST_TYPE":"001"},"VIP_FLAG":{"VIP_FLAG":"true"}},{"CUST_TYPE":{"CUST_TYPE":"002"},"VIP_FLAG":{"VIP_FLAG":"false"}},{"CUST_TYPE":{"CUST_TYPE":"003"},"VIP_FLAG":{"VIP_FLAG":"false"}}]},"TOTAL_PAGE":{"TOTAL_PAGE":"10"},"CURRENT_PAGE":{"CURRENT_PAGE":"1"}},"HEAD":{"ACTION_CODE":{"ACTION_CODE":"1"},"ORIGIN_DOMAIN":{"ORIGIN_DOMAIN":"kefuxit"},"BUSI_CODE":{"BUSI_CODE":"QUERYCUST"},"HOME_DOMAIN":{"HOME_DOMAIN":"CUGCRM"},"TRANS_ID":{"TRANS_ID":"20160220160635123456"},"RET_MSG":{"RET_MSG":"success"},"RET_CODE":{"RET_CODE":"0000"}}}

格式化之后的结果如下:

  1. map :
  2. {
  3. BODY={
  4. TOTAL_RECORDS={TOTAL_RECORDS=20},
  5. CUSTINFOLIST={
  6. CUSTINFO=[
  7. {
  8. CUST_TYPE={CUST_TYPE=001},
  9. VIP_FLAG={VIP_FLAG=true}
  10. },
  11. {
  12. CUST_TYPE={CUST_TYPE=002},
  13. VIP_FLAG={VIP_FLAG=false}
  14. },
  15. {
  16. CUST_TYPE={CUST_TYPE=003},
  17. VIP_FLAG={VIP_FLAG=false}
  18. }
  19. ]
  20. },
  21. TOTAL_PAGE={TOTAL_PAGE=10},
  22. CURRENT_PAGE={CURRENT_PAGE=1}
  23. },
  24. HEAD={
  25. ACTION_CODE={ACTION_CODE=1},
  26. ORIGIN_DOMAIN={ORIGIN_DOMAIN=kefuxit},
  27. BUSI_CODE={BUSI_CODE=QUERYCUST},
  28. HOME_DOMAIN={HOME_DOMAIN=CUGCRM},
  29. TRANS_ID={TRANS_ID=20160220160635123456},
  30. RET_MSG={RET_MSG=success},
  31. RET_CODE={RET_CODE=0000}
  32. }
  33. }
  34. Json:
  35. {
  36. "BODY":{
  37. "TOTAL_RECORDS":{"TOTAL_RECORDS":"20"},
  38. "CUSTINFOLIST":{
  39. "CUSTINFO":[
  40. {
  41. "CUST_TYPE":{"CUST_TYPE":"001"},
  42. "VIP_FLAG":{"VIP_FLAG":"true"}
  43. },
  44. {
  45. "CUST_TYPE":{"CUST_TYPE":"002"},
  46. "VIP_FLAG":{"VIP_FLAG":"false"}
  47. },
  48. {
  49. "CUST_TYPE":{"CUST_TYPE":"003"},
  50. "VIP_FLAG":{"VIP_FLAG":"false"}
  51. }
  52. ]
  53. },
  54. "TOTAL_PAGE":{"TOTAL_PAGE":"10"},
  55. "CURRENT_PAGE":{"CURRENT_PAGE":"1"}
  56. },
  57. "HEAD":{
  58. "ACTION_CODE":{"ACTION_CODE":"1"},
  59. "ORIGIN_DOMAIN":{"ORIGIN_DOMAIN":"kefuxit"},
  60. "BUSI_CODE":{"BUSI_CODE":"QUERYCUST"},
  61. "HOME_DOMAIN":{"HOME_DOMAIN":"CUGCRM"},
  62. "TRANS_ID":{"TRANS_ID":"20160220160635123456"},
  63. "RET_MSG":{"RET_MSG":"success"},
  64. "RET_CODE":{"RET_CODE":"0000"}
  65. }
  66. }

发表评论

表情:
评论列表 (有 0 条评论,305人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Java 读取XML文件(DOM)。

    XML文件的一个常用用途是保存数据,例如我们可以将连接数据库的相关信息保存到一个xml文件中,程序通过读取xml文件的内容获取信息。这样当数据库的连接信息改变时,我们只需要修改

    相关 Java读取层级xml文件

    最近在做国际客服北京职场的项目,需要提供一个接口服务端的能力,也就是需要开发一个http+xml的协议,入参和出参均为Map格式,各系统间的请求或应答是以xml格式封装的。在将