XML转换为Map通用算法实现 Java版本(Stax实现)

目前项目中需要将XML转换为Map,下面给出了自己的代码实现。

后续将为大家提供Dom版本的实现。

请各路大神给予各种优良实现。

场景:

在项目中需要解析XML文本字符串,需要将XML文本字符串映射为Map格式的对象。

需求:

1、为了提高性能,需要使用Stax进行解析

2、Map结构内部需要支持List、Map、String三种数据格式

示例:

例一:字符串直接转换为Map结构

 *     字符串:<name>BurceLiu</name><age>18</age>

 *     转换为的Map结构:{age=18, name=BurceLiu}
 
  
例二:字符串转换为Map结构,Map内部嵌套Map的结构

 *     字符串:<student><name>BurceLiu</name><age>18</age></student>

 *     转换为的Map结构:{student={age=18, name=BurceLiu}}
例三:字符串转换为Map结构,Map内部嵌套为List的结构,List内部为Map

 *     字符串:<student><name>BurceLiu</name><age>18</age></student><student><name>BurceLi</name><age>28</age></student>

 *     转换为的Map结构:{student=[{age=18, name=BurceLiu}, {age=28, name=BurceLi}]}
例四:字符串转换为Map结构,Map内部嵌套Map,Map内部嵌套List
* 字符串:<students><student><name>BurceLiu</name><age>18</age></student><student><name>BurceLi</name><age>28</age></student></students> 
* 转换为的Map结构:{students={student=[{age=18, name=BurceLiu}, {age=28, name=BurceLi}]}}
例五:字符串转换为List结构

 *     字符串:<str>str1</str><str>str2</str><str>str3</str>

 *     转换为的Map结构:{str=[str1, str2, str3]}
 
  

代码实现

1、接口定义

定义解析接口,提供2个核心方法

public interface IXMLParser {

    

    /**

     * xml格式字符串转换为Map

     * @param xml

     * @return

     */

    public Map<String, Object> parse(String xml);

    

    /**

     * 初始化动作

     * 可以设置初始化动作,例如根节点名称,

     */

    public void init();

}

 

2、实现类

具体实现类,采用Stax技术实现该方案

 

  1 package com.juxtapose.xml.parser;

  2 

  3 import java.io.StringReader;

  4 import java.util.ArrayList;

  5 import java.util.HashMap;

  6 import java.util.List;

  7 import java.util.Map;

  8 import java.util.concurrent.atomic.AtomicInteger;

  9 

 10 import javax.xml.stream.XMLInputFactory;

 11 import javax.xml.stream.XMLStreamConstants;

 12 import javax.xml.stream.XMLStreamReader;

 13 

 14 /**

 15  * xml字符串解析器实现类.<br>

 16  * xml字符串转换为Map对象.<br>

 17  * 转换后的数据类型为Map、List、String三种数据类型.<br>

 18  *

 19  * @author burceliu (mailto:[email protected])

 20  */

 21 

 22 public class XMLParserStaxImpl implements IXMLParser {

 23     

 24     public static final String NODE_ELEMENT_NAME = "root";

 25     public static final String NODE_DEFAULT_VALUE = "";

 26     

 27     private String rootName;            //根节点

 28     private String defaultNullValue;    //节点没有值的情况下默认值

 29     

 30     private static  XMLInputFactory factory = XMLInputFactory.newInstance(); 

 31     static {

 32         factory.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, Boolean.FALSE);

 33         factory.setProperty(XMLInputFactory.IS_COALESCING, Boolean.TRUE);  

 34     }

 35     

 36     /* (non-Javadoc)

 37      * @see com.juxtapose.xml.parser.IXMLParser#parse(java.lang.String)

 38      */

 39     public Map<String, Object> parse(String xml) {

 40         Map<String, Object> map = new HashMap<String, Object>();

 41         StringReader stringReader = null;

 42         try{

 43             stringReader = new StringReader(xml);

 44             XMLStreamReader reader = factory.createXMLStreamReader(stringReader);  

 45             map = parse(reader);

 46         }catch(Throwable t){

 47             throw new RuntimeException(t);

 48         }finally{

 49             if(null != stringReader){

 50                 try {

 51                     stringReader.close();

 52                 } catch (Exception e) {

 53                     throw new RuntimeException(e);

 54                 }

 55             }

 56         }

 57         return map;

 58     }

 59 

 60     /* (non-Javadoc)

 61      * @see com.juxtapose.xml.parser.IXMLParser#init()

 62      */

 63     public void init() {

 64         if(this.getRootName() == null){

 65             this.setRootName(NODE_ELEMENT_NAME);

 66             this.setDefaultNullValue(NODE_DEFAULT_VALUE);

 67         }

 68     }

 69     

 70     @SuppressWarnings({ "unchecked", "rawtypes" })

 71     private Map<String, Object> parse(XMLStreamReader reader) throws Throwable{

 72         Map<String, Object> map = new HashMap<String, Object>();

 73         Map<String, Object> currentMap = map;

 74         int event = reader.getEventType();

 75         List<String> names = new ArrayList<String>();

 76         NodeAmount nodeAmount = new NodeAmount();

 77         int taglength = 0;

 78         String tagName = null;

 79         String tagValue = this.defaultNullValue;

 80         while(true){

 81             switch (event) {  

 82             case XMLStreamConstants.START_DOCUMENT:

 83                 break;  

 84             case XMLStreamConstants.START_ELEMENT:

 85                 tagValue = this.defaultNullValue;

 86                 tagName = reader.getLocalName();

 87                 if(this.rootName.equals(tagName)){

 88                     break;

 89                 }

 90                 names.add(tagName);

 91                 taglength++;

 92                 

 93                 currentMap = map;

 94                 if(taglength > 1){

 95                     for(int i=0;i< taglength-1;i++){

 96                         Object object = currentMap.get(names.get(i));

 97                         if(null == object){

 98                             object = new HashMap<String, Object>();

 99                             currentMap.put(names.get(i), object);

100                             currentMap = (Map<String, Object>)object;

101                         }else{

102                             int currentTagNameSize = nodeAmount.getSize(i + 1 + "" + names.get(i));

103                             if( currentTagNameSize > 1){

104                                 if(object instanceof Map){

105                                     List parentList = new ArrayList();

106                                     parentList.add(object);

107                                     Map tempMap = new HashMap();

108                                     parentList.add(tempMap);

109                                     currentMap.put(names.get(i), parentList);

110                                     currentMap = tempMap;

111                                 }else if(object instanceof List){

112                                     List parentList = (List)object;

113                                     int parentListSize = parentList.size();

114                                     if(parentListSize != currentTagNameSize){

115                                         Map tempMap = new HashMap();

116                                         parentList.add(tempMap);

117                                         currentMap = tempMap;

118                                     }else{

119                                         Map tempMap = (Map) parentList.get(parentList.size()-1);

120                                         currentMap = tempMap;

121                                     }

122                                 }

123                             }else{

124                                 currentMap = (Map<String, Object>)object;

125                             }

126                         }

127                     }

128                 }

129                 nodeAmount.add(names.size() + tagName);

130                 break;  

131             case XMLStreamConstants.CHARACTERS: 

132                 tagValue = reader.getText();

133                  break;

134             case XMLStreamConstants.END_ELEMENT: 

135                 tagName = reader.getLocalName();

136                 if(this.rootName.equals(tagName)){

137                     break;

138                 }

139                 

140                 currentMap = map;

141                 if(taglength > 1){

142                     for(int i=0;i< taglength-1;i++){

143                         Object object = currentMap.get(names.get(i));

144                         if(null == object){

145                             //nothing to do

146                         }else{

147                             if(object instanceof List){

148                                 List list = (List)object;

149                                 currentMap = (Map)list.get(list.size() -1);

150                             }else if(object instanceof Map){

151                                 currentMap = (Map)object;

152                             }

153                         }

154                     }

155                 }

156                 

157                 Object oldValue = currentMap.get(tagName);

158                 if(!currentMap.containsKey(tagName)){

159                     currentMap.put(tagName, tagValue);

160                     nodeAmount.remove(names.size() + tagName);

161                 }else{

162                     if(oldValue instanceof List){

163                         List list = (List)oldValue;

164                         if(list.size() > 0){

165                             Object obj = list.get(0);

166                             if(obj instanceof String){

167                                 ((List)oldValue).add(tagValue);

168                                 nodeAmount.remove(names.size() + tagName);

169                             }

170                         }

171                     }else if(oldValue instanceof Map){

172                         

173                     }else{

174                         List tmpList = new ArrayList();

175                         currentMap.put(tagName, tmpList);

176                         tmpList.add(oldValue);

177                         tmpList.add(tagValue);

178                         nodeAmount.remove(names.size() + tagName);

179                     }

180                 }

181                 

182                 tagValue = this.defaultNullValue;

183                 names.remove(names.size()-1);

184                 taglength--;

185                 break;  

186             case XMLStreamConstants.END_DOCUMENT:  

187                 break;  

188             }  

189 

190             if (!reader.hasNext()) {  

191                 break;  

192             }  

193             event = reader.next();  

194         }

195         return map;

196     }

197 

198     public String getRootName() {

199         return rootName;

200     }

201 

202     public void setRootName(String rootName) {

203         this.rootName = rootName;

204     }

205 

206     public String getDefaultNullValue() {

207         return defaultNullValue;

208     }

209 

210     public void setDefaultNullValue(String defaultNullValue) {

211         this.defaultNullValue = defaultNullValue;

212     }

213     

214     class NodeAmount{

215         private Map<String, AtomicInteger> map =new HashMap<String, AtomicInteger>();

216         

217         public void add(String nodeName){

218             AtomicInteger integer = map.get(nodeName);

219             if(null == integer){

220                 integer = new AtomicInteger(0);

221                 map.put(nodeName, integer);

222             }

223             integer.incrementAndGet();

224         }

225         

226         public void remove(String nodeName){

227             AtomicInteger integer = map.get(nodeName);

228             if(null != integer){

229                 integer.decrementAndGet();

230             }

231         }

232         

233         public int getSize(String nodeName){

234             AtomicInteger integer = map.get(nodeName);

235             if(null == integer){

236                 integer = new AtomicInteger(0);

237                 map.put(nodeName, integer);

238             }

239             return integer.intValue();

240         }

241     }

242 

243 }

244 

245 /*

246  * 修改历史

247  * $Log$ 

248  */

3、单元测试

 1 package test.com.juxtapose.xml.parser;

 2 

 3 import java.util.Map;

 4 

 5 import org.junit.After;

 6 import org.junit.AfterClass;

 7 import org.junit.Before;

 8 import org.junit.BeforeClass;

 9 import org.junit.Test;

10 

11 import com.juxtapose.xml.parser.IXMLParser;

12 import com.juxtapose.xml.parser.XMLParserStaxImpl;

13 

14 /**

15  *

16  * @author burceliu (mailto:[email protected])

17  */

18 

19 public class TestXMLParserStaxImpl {

20 

21     /**

22      * @throws java.lang.Exception

23      */

24     @BeforeClass

25     public static void setUpBeforeClass() throws Exception {

26     }

27 

28     /**

29      * @throws java.lang.Exception

30      */

31     @AfterClass

32     public static void tearDownAfterClass() throws Exception {

33     }

34 

35     /**

36      * @throws java.lang.Exception

37      */

38     @Before

39     public void setUp() throws Exception {

40     }

41 

42     /**

43      * @throws java.lang.Exception

44      */

45     @After

46     public void tearDown() throws Exception {

47     }

48 

49     @Test

50     public void test() {

51         IXMLParser parser =  new XMLParserStaxImpl();

52         parser.init();

53         String xml = "<root><student><name>BurceLiu</name><age>18</age></student></root>";

54         Map<String, Object> result = parser.parse(xml);

55         System.out.println(result);

56         xml = "<root><student><name>BurceLiu</name><age>18</age></student><student><name>BurceLi</name><age>28</age></student></root>";

57         result = parser.parse(xml);

58         System.out.println(result);

59         xml = "<root><str>str1</str><str>str2</str><str>str3</str></root>";

60         result = parser.parse(xml);

61         System.out.println(result);

62         xml = "<root><students><student><name>BurceLiu</name><age>18</age></student><student><name>BurceLi</name><age>28</age></student></students></root>";

63         result = parser.parse(xml);

64         System.out.println(result);

65         xml = "<root><name>BurceLiu</name><age>18</age></root>";

66         result = parser.parse(xml);

67         System.out.println(result);

68     }

69 

70 }

71 

72 /*

73  * 修改历史

74  * $Log$ 

75  */

 

4、测试结果

观察控制台的输出结果:

{student={age=18, name=BurceLiu}}

{student=[{age=18, name=BurceLiu}, {age=28, name=BurceLi}]}

{str=[str1, str2, str3]}

{students={student=[{age=18, name=BurceLiu}, {age=28, name=BurceLi}]}}

{age=18, name=BurceLiu}

 

如有任何问题,可以通过[email protected]与我取得联系。

 

你可能感兴趣的:(java)