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

来源:互联网 发布:精易编程助手教程 编辑:程序博客网 时间:2024/06/08 17:07

目前项目中需要将XML转换为Map,下面给出了自己的代码实现。请各路大神提供更好的代码实现。

场景:

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

需求:

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

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

示例:

例一: * 字符串:<name>BurceLiu</name><age>18</age> * 转换为的Map结构:{age=18, name=BurceLiu}
例二: * 字符串:<student><name>BurceLiu</name><age>18</age></student> * 转换为的Map结构:{student={age=18, name=BurceLiu}}

例三: * 字符串:<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}]}

例四: * 字符串:<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}]}}

例五: * 字符串:<str>str1</str><str>str2</str><str>str3</str> * 转换为的Map结构:{str=[str1, str2, str3]}


代码实现

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

public interface IXMLParser {/** * xml格式字符串转换为Map * @param xml * @return */public Map<String, Object> parse(String xml);/** * 初始化动作 * 可以设置初始化动作,例如根节点名称, */public void init();}
具体实现类,采用Stax技术实现该方案

package com.juxtapose.xml.parser;import java.io.StringReader;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;import java.util.concurrent.atomic.AtomicInteger;import javax.xml.stream.XMLInputFactory;import javax.xml.stream.XMLStreamConstants;import javax.xml.stream.XMLStreamReader;/** * xml字符串解析器实现类.<br> * xml字符串转换为Map对象.<br> * 转换后的数据类型为Map、List、String三种数据类型.<br> * * @author burceliu (mailto:jxta.liu@gmail.com) */public class XMLParserStaxImpl implements IXMLParser {public static final String NODE_ELEMENT_NAME = "root";public static final String NODE_DEFAULT_VALUE = "";private String rootName;//根节点private String defaultNullValue;//节点没有值的情况下默认值private static  XMLInputFactory factory = XMLInputFactory.newInstance(); static {factory.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, Boolean.FALSE);    factory.setProperty(XMLInputFactory.IS_COALESCING, Boolean.TRUE);  }/* (non-Javadoc) * @see com.juxtapose.xml.parser.IXMLParser#parse(java.lang.String) */public Map<String, Object> parse(String xml) {Map<String, Object> map = new HashMap<String, Object>();StringReader stringReader = null;try{stringReader = new StringReader(xml);XMLStreamReader reader = factory.createXMLStreamReader(stringReader);  map = parse(reader);}catch(Throwable t){throw new RuntimeException(t);}finally{if(null != stringReader){try {stringReader.close();} catch (Exception e) {throw new RuntimeException(e);}}}        return map;    }/* (non-Javadoc) * @see com.juxtapose.xml.parser.IXMLParser#init() */public void init() {if(this.getRootName() == null){this.setRootName(NODE_ELEMENT_NAME);this.setDefaultNullValue(NODE_DEFAULT_VALUE);}}@SuppressWarnings({ "unchecked", "rawtypes" })private Map<String, Object> parse(XMLStreamReader reader) throws Throwable{Map<String, Object> map = new HashMap<String, Object>();Map<String, Object> currentMap = map;int event = reader.getEventType();List<String> names = new ArrayList<String>();NodeAmount nodeAmount = new NodeAmount();int taglength = 0;        String tagName = null;        String tagValue = this.defaultNullValue;while(true){            switch (event) {              case XMLStreamConstants.START_DOCUMENT:                break;              case XMLStreamConstants.START_ELEMENT:            tagValue = this.defaultNullValue;            tagName = reader.getLocalName();            if(this.rootName.equals(tagName)){            break;            }            names.add(tagName);            taglength++;                        currentMap = map;            if(taglength > 1){            for(int i=0;i< taglength-1;i++){            Object object = currentMap.get(names.get(i));            if(null == object){            object = new HashMap<String, Object>();            currentMap.put(names.get(i), object);            currentMap = (Map<String, Object>)object;            }else{            int currentTagNameSize = nodeAmount.getSize(i + 1 + "" + names.get(i));            if( currentTagNameSize > 1){            if(object instanceof Map){            List parentList = new ArrayList();            parentList.add(object);            Map tempMap = new HashMap();            parentList.add(tempMap);            currentMap.put(names.get(i), parentList);            currentMap = tempMap;            }else if(object instanceof List){            List parentList = (List)object;            int parentListSize = parentList.size();            if(parentListSize != currentTagNameSize){            Map tempMap = new HashMap();            parentList.add(tempMap);            currentMap = tempMap;            }else{            Map tempMap = (Map) parentList.get(parentList.size()-1);            currentMap = tempMap;            }            }            }else{            currentMap = (Map<String, Object>)object;            }            }            }            }            nodeAmount.add(names.size() + tagName);                break;              case XMLStreamConstants.CHARACTERS:             tagValue = reader.getText();                 break;            case XMLStreamConstants.END_ELEMENT:             tagName = reader.getLocalName();            if(this.rootName.equals(tagName)){            break;            }                        currentMap = map;            if(taglength > 1){            for(int i=0;i< taglength-1;i++){            Object object = currentMap.get(names.get(i));            if(null == object){            //nothing to do            }else{            if(object instanceof List){            List list = (List)object;            currentMap = (Map)list.get(list.size() -1);            }else if(object instanceof Map){            currentMap = (Map)object;            }            }            }            }                        Object oldValue = currentMap.get(tagName);            if(!currentMap.containsKey(tagName)){            currentMap.put(tagName, tagValue);            nodeAmount.remove(names.size() + tagName);            }else{            if(oldValue instanceof List){            List list = (List)oldValue;            if(list.size() > 0){            Object obj = list.get(0);            if(obj instanceof String){            ((List)oldValue).add(tagValue);            nodeAmount.remove(names.size() + tagName);            }            }            }else if(oldValue instanceof Map){                        }else{            List tmpList = new ArrayList();            currentMap.put(tagName, tmpList);            tmpList.add(oldValue);            tmpList.add(tagValue);            nodeAmount.remove(names.size() + tagName);            }            }                        tagValue = this.defaultNullValue;            names.remove(names.size()-1);            taglength--;                break;              case XMLStreamConstants.END_DOCUMENT:                  break;              }              if (!reader.hasNext()) {                  break;              }              event = reader.next();          }return map;}public String getRootName() {return rootName;}public void setRootName(String rootName) {this.rootName = rootName;}public String getDefaultNullValue() {return defaultNullValue;}public void setDefaultNullValue(String defaultNullValue) {this.defaultNullValue = defaultNullValue;}class NodeAmount{private Map<String, AtomicInteger> map =new HashMap<String, AtomicInteger>();public void add(String nodeName){AtomicInteger integer = map.get(nodeName);if(null == integer){integer = new AtomicInteger(0);map.put(nodeName, integer);}integer.incrementAndGet();}public void remove(String nodeName){AtomicInteger integer = map.get(nodeName);if(null != integer){integer.decrementAndGet();}}public int getSize(String nodeName){AtomicInteger integer = map.get(nodeName);if(null == integer){integer = new AtomicInteger(0);map.put(nodeName, integer);}return integer.intValue();}}}/* * 修改历史 * $Log$  */

单元测试:

package test.com.juxtapose.xml.parser;import java.util.Map;import org.junit.After;import org.junit.AfterClass;import org.junit.Before;import org.junit.BeforeClass;import org.junit.Test;import com.juxtapose.xml.parser.IXMLParser;import com.juxtapose.xml.parser.XMLParserStaxImpl;/** * * @author burceliu (mailto:jxta.liu@gmail.com) */public class TestXMLParserStaxImpl {/** * @throws java.lang.Exception */@BeforeClasspublic static void setUpBeforeClass() throws Exception {}/** * @throws java.lang.Exception */@AfterClasspublic static void tearDownAfterClass() throws Exception {}/** * @throws java.lang.Exception */@Beforepublic void setUp() throws Exception {}/** * @throws java.lang.Exception */@Afterpublic void tearDown() throws Exception {}@Testpublic void test() {IXMLParser parser =  new XMLParserStaxImpl();parser.init();String xml = "<root><student><name>BurceLiu</name><age>18</age></student></root>";Map<String, Object> result = parser.parse(xml);System.out.println(result);xml = "<root><student><name>BurceLiu</name><age>18</age></student><student><name>BurceLi</name><age>28</age></student></root>";result = parser.parse(xml);System.out.println(result);xml = "<root><str>str1</str><str>str2</str><str>str3</str></root>";result = parser.parse(xml);System.out.println(result);xml = "<root><students><student><name>BurceLiu</name><age>18</age></student><student><name>BurceLi</name><age>28</age></student></students></root>";result = parser.parse(xml);System.out.println(result);xml = "<root><name>BurceLiu</name><age>18</age></root>";result = parser.parse(xml);System.out.println(result);}}/* * 修改历史 * $Log$  */

观察控制台的输出结果:

{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}



0 0
原创粉丝点击