码迷,mamicode.com
首页 > 编程语言 > 详细

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

时间:2015-02-10 10:31:14      阅读:1180      评论:0      收藏:0      [点我收藏+]

标签:

目前项目中需要将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
	 */
	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
	}

	/**
	 * @throws java.lang.Exception
	 */
	@AfterClass
	public static void tearDownAfterClass() throws Exception {
	}

	/**
	 * @throws java.lang.Exception
	 */
	@Before
	public void setUp() throws Exception {
	}

	/**
	 * @throws java.lang.Exception
	 */
	@After
	public void tearDown() throws Exception {
	}

	@Test
	public 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}




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

标签:

原文地址:http://www.cnblogs.com/jxta/p/4283107.html

(0)
(1)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!