`
mengqingyu
  • 浏览: 334334 次
  • 性别: Icon_minigender_1
  • 来自: 天津
社区版块
存档分类
最新评论

dom4j+反射,面向对象方式的xml格式转换

阅读更多
工作中遇到了两种不同表单设计器保存xml之间的相互转换需求,在此做个记录,利用dom4j+反射的面向对象方式实现的,其中因为需求原因有部分定制代码,不过稍作修改可以改成通用的文件转换功能。实体bean在此省略。。。


package com.test.xml.main;

public interface IConvertXml {
	
	/**
	 * 
	 * @function:读xml
	 * @param obj  需要存储的对象
	 * @param filePath   xml文件路径
	 * @return
	 * @throws Exception
	 * @author: mengqingyu    2012-8-27 下午02:06:21
	 */
	Object readXml(Object obj, String filePath) throws Exception;
	
	/**
	 * 
	 * @function:
	 * @param obj    需要输出到xml中的对象
	 * @param filePath   xml文件路径
	 * @throws Exception
	 * @author: mengqingyu    2012-8-27 下午02:07:00
	 */
	void writeXml(Object obj, String filePath) throws Exception;
}

package com.test.xml.main;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;

/**
 * 
 * 类功能描述:2种不同规范格式的xml之间的转换
 *
 * @author <a href="mailto:qingyu.meng21@gmail.com">mengqingyu </a>
 * @version $Id: codetemplates.xml,v 1.1 2009/03/06 01:13:01 mengqingyu Exp  $
 * Create:  2012-9-3 下午01:39:16
 */
public class ConvertXml implements IConvertXml{
	
	private final String packagePath = "com.test.xml.bean";
	
	private Map<String,String> fieldMap = new HashMap<String,String>();
	
	private Map<String,String> itemMap = new HashMap<String,String>();
	
	public ConvertXml() {
		super();
		initMap();
	}

	public Object readXml(Object obj, String filePath) throws Exception {
		SAXReader reader = new SAXReader();
        Document  document = reader.read(new File(filePath.toString().replace("file:/", "")));
        
        Element rootElm = document.getRootElement();
        initBean(obj, rootElm, false);
        
        List<Element> elements = rootElm.selectNodes("elements/band/frame/*");
        for(Element element:elements){
        	String className = getClassName(element.getName());
        	if(className==null)continue;
        	String classPath = packagePath+"."+className;
        	Object subObj = Class.forName(classPath).newInstance();
        	for(Iterator it=element.elementIterator();it.hasNext();){
        		Element elementSub = (Element)it.next();
        		initBean(subObj, elementSub, true);
        	}
            Field[] field = obj.getClass().getDeclaredFields();
            for (int i=0;i<field.length;i++){  
	            if (field[i].getName().equalsIgnoreCase(className+"s")){ 
	            	Set<Object> items = (Set<Object>)this.getField(field[i], obj);
	            	items.add(subObj);
            	}   
            } 
        }
        return obj;
	}
	
	public void writeXml(Object obj, String filePath) throws IllegalArgumentException, IllegalAccessException, IOException {
		Document document = DocumentHelper.createDocument();
		Element root = document.addElement("form");//根节点
		
        Field[] field = obj.getClass().getDeclaredFields();    
        for (int i=0;i<field.length;i++){
        	if("interface java.util.Set".equals(field[i].getType().toString())){
        		Set<Object> items = (Set<Object>)this.getField(field[i], obj);
        		for(Object o:items){
        			Element element = root.addElement("item");
        			Field[] fieldSub = o.getClass().getDeclaredFields(); 
        	        for (int j=0;j<fieldSub.length;j++){
        	        	element.addAttribute(fieldSub[j].getName(), (String)this.getField(fieldSub[j], o));
        	        }
        		}
        	}
        	else{
        		root.addAttribute(field[i].getName(), (String)this.getField(field[i], obj));
        	}
        }
        root.addElement("heji").addAttribute("value", "");
        root.addElement("shenhe").addAttribute("value", "");
        
		OutputFormat format = OutputFormat.createPrettyPrint();
		format.setEncoding("GBK");   // 设置XML文件的编码格式
        XMLWriter writer = new XMLWriter(new FileOutputStream(filePath.toString().replace("file:/", "")), format);   
        writer.setEscapeText(false);
        writer.write(document);  
        writer.flush(); 
        writer.close(); 
	}
	
	/**
	 * 
	 * @function:初始化map 这里存放了两个xml属性映射关系
	 * @author: mengqingyu    2012-8-27 下午02:05:58
	 */
	private void initMap() {
		//目标文件的属性名和源文件的属性名映射
		fieldMap.put("name", "title");
		fieldMap.put("canvasWidth", "formwidth");
		fieldMap.put("canvasHeight", "formheight");
		fieldMap.put("key", "i_id");
		fieldMap.put("x", "i_x");
		fieldMap.put("y", "i_y");
		fieldMap.put("width", "i_width");
		fieldMap.put("height", "i_height");
		fieldMap.put("columnName", "i_code");
		fieldMap.put("columnLen", "i_length");
		fieldMap.put("keyname", "i_value");
		fieldMap.put("value", "i_value");
		fieldMap.put("fontName", "i_style");
		fieldMap.put("fontSize", "i_style");
		fieldMap.put("textAlignment", "i_style");
		fieldMap.put("size", "i_style");
		fieldMap.put("readOnly", "i_readonly");
		fieldMap.put("maxlength", "i_length");
		fieldMap.put("tabIndex", "i_tabseq");
		fieldMap.put("dataType", "i_type");
		
		//源文件的标签名和实体bean类名的映射
		itemMap.put("label", "Label");
		itemMap.put("line", "Line");
		itemMap.put("textfield", "Textfield");
		itemMap.put("checkbox", "Checkbox");
	}
	
	/**
	 * 
	 * @function:通过xml中的内容初始化bean
	 * @param obj  要初始化的bean
	 * @param element   文档元素
	 * @param flag  是否递归解析子节点
	 * @throws Exception
	 * @author: mengqingyu    2012-8-27 下午02:05:10
	 */
	private void initBean(Object obj,Element element, boolean flag) throws Exception{
		for(Iterator it=element.attributeIterator();it.hasNext();){//遍历当前节点的所有属性
			Attribute attribute = (Attribute) it.next();
			Field[] field = obj.getClass().getDeclaredFields();
			for (int i=0;i<field.length;i++){  //根据xml内容赋值到对象中,使用对象中默认值不需要重新赋值
				if (field[i].getName().equals(getfieldValue(attribute.getName()))){
					this.customAttribute(field[i], element, attribute, obj);//一些定制处理
					this.invokeMethod(this.setMethodName(field[i].getName()), obj, attribute.getText());
				}   
			} 
		}
		if(flag==true){//递归子节点
			List<Element> subElements = element.elements();
			for(Element subElement:subElements){
				this.initBean(obj, subElement, true);
			}
		}
	}
	
	/**
	 * 
	 * @function:这里添加了一些非规则的定制内容转换
	 * @param field 类的属性
	 * @param element 文档标签对象
	 * @param attribute 标签里的属性
	 * @param obj 属性所属类对象
	 * @throws IllegalArgumentException
	 * @throws SecurityException
	 * @throws IllegalAccessException
	 * @throws InvocationTargetException
	 * @throws NoSuchMethodException
	 * @author: mengqingyu    2012-8-29 上午10:31:47
	 */
	private void customAttribute(Field field, Element element, Attribute attribute, Object obj) throws IllegalArgumentException, SecurityException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
		if("text".equals(element.getName())){
			if("keyname".equals(attribute.getName())){
				if(element.getText().indexOf("javascript")==-1){
					attribute.setText(element.getText().replace("\n", "<br/>"));
				}
				else{
					attribute.setText("<a href=\"#\">此处添加事件</a>");
				}
			}
		}
		else if("i_style".equals(field.getName())){
			String value = (String)this.invokeMethod(this.getMethodName(field.getName()),obj);
			if("fontName".equals(attribute.getName())){
				attribute.setText(value.replace("宋体", attribute.getText()));
			}
			else if("size".equals(attribute.getName())||"fontSize".equals(attribute.getName())){
				attribute.setText(value.replace("12", attribute.getText()));
			}
			else if("textAlignment".equals(attribute.getName())){
				attribute.setText(value.replace("left", attribute.getText().toLowerCase()));
			}
		}
		else if("databaseElement".equals(element.getName())){
			if("dataType".equals(attribute.getName())&&"varchar".equals(attribute.getValue())){
				attribute.setText("textfield");
				this.invokeMethod(this.setMethodName("i_data_type"), obj, "字符");
			}
			else if("dataType".equals(attribute.getName())&&"decimal".equals(attribute.getValue())){
				attribute.setText("numberfield");
				this.invokeMethod(this.setMethodName("i_data_type"), obj, "数值");
			}
		}
	}
	/**
	 * 
	 * @function:执行方法
	 * @param methodName 方法名
	 * @param object 方法所在对象
	 * @param value  方法中的参数值
	 * @throws IllegalArgumentException
	 * @throws IllegalAccessException
	 * @throws InvocationTargetException
	 * @throws SecurityException
	 * @throws NoSuchMethodException
	 * @author: mengqingyu    2012-8-27 下午02:03:51
	 */
	private void invokeMethod(String methodName, Object object,Object value) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, SecurityException, NoSuchMethodException {   
		Method method = object.getClass().getMethod(methodName,String.class);
		method.invoke(object,value);
	} 
	
	/**
	 * 
	 * @function:执行方法
	 * @param methodName 方法名
	 * @param object 方法所在对象
	 * @return
	 * @throws IllegalArgumentException
	 * @throws IllegalAccessException
	 * @throws InvocationTargetException
	 * @throws SecurityException
	 * @throws NoSuchMethodException
	 * @author: mengqingyu    2012-8-28 下午04:27:38
	 */
	private Object invokeMethod(String methodName, Object object) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, SecurityException, NoSuchMethodException {   
		Method method = object.getClass().getMethod(methodName);
		return method.invoke(object);
	} 
	
	/**
	 * 
	 * @function:获得属性值
	 * @param field   属性对象
	 * @param object  属性所属类对象
	 * @return
	 * @throws IllegalArgumentException
	 * @throws IllegalAccessException
	 * @author: mengqingyu    2012-8-27 下午02:03:40
	 */
	private Object getField(Field field,Object object) throws IllegalArgumentException, IllegalAccessException {   
		field.setAccessible(true);//设置属性可以修改   
		return field.get(object);
	} 
	
	/**
	 * 
	 * @function:通过属性生成get方法名
	 * @param str
	 * @return
	 * @author: mengqingyu    2012-8-27 下午02:03:27
	 */
	private String getMethodName(String str){   
		return "get"+ firstToUpperCase(str);   
	}   
	
	/**
	 * 
	 * @function:通过属性生成set方法名
	 * @param str
	 * @return
	 * @author: mengqingyu    2012-8-27 下午02:03:27
	 */
	private String setMethodName(String str){   
		return "set"+ firstToUpperCase(str);   
	}   
	
	/**
	 * 首字母大写
	 */
	private String firstToUpperCase(String str){   
		return Character.toUpperCase(str.charAt(0)) + str.substring(1);   
	}
	
	/**
	 * 
	 * @function:获得两组xml标签中属性的对应关系
	 * @param key
	 * @return
	 * @author: mengqingyu    2012-8-27 下午02:02:48
	 */
	private String getfieldValue(String key){
		return fieldMap.get(key);
	}
	
	/**
	 * 
	 * @function:获得标签与类的关系
	 * @param key
	 * @return
	 * @author: mengqingyu    2012-8-27 下午02:02:23
	 */
	private String getClassName(String key){
		return itemMap.get(key);
	}
}

package com.test.xml.main;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;

import org.dom4j.DocumentException;

import com.test.xml.bean.FormFlow;

public class MainXml {

	/**
	 * @function:
	 * @param args
	 * @author: mengqingyu    2012-5-2 下午04:56:17
	 * @throws DocumentException 
	 * @throws IllegalAccessException 
	 * @throws InstantiationException 
	 * @throws NoSuchMethodException 
	 * @throws SecurityException 
	 * @throws InvocationTargetException 
	 * @throws IllegalArgumentException 
	 * @throws ClassNotFoundException 
	 * @throws IOException 
	 */
	public static void main(String[] args) throws Exception {
		IConvertXml convertXml = new ConvertXml();
		FormFlow form = (FormFlow)convertXml.readXml(new FormFlow(),MainXml.class.getResource("/")+"xt.xml");
		convertXml.writeXml(form, MainXml.class.getResource("/")+"xt_new.xml");
	}
}
分享到:
评论

相关推荐

    spring dom4j 解析 依赖DI注入 ioc 反转 反射原理

    当Spring启动时,会读取配置文件(通常是`applicationContext.xml`),DOM4J则负责将XML内容转换成内存中的对象结构。通过这种方式,Spring能够理解配置文件中的bean定义,包括bean的类型、属性、依赖关系等,为后续...

    XML操作 面向对象其一(封装) 序列化 反序列化 练习

    本练习将重点讲解XML与面向对象编程中的封装、以及序列化和反序列化的概念。 首先,面向对象编程(Object-Oriented Programming, OOP)是程序设计的一种重要范式,它的核心思想是将数据和处理这些数据的方法封装在...

    java 根据javaBean反射自定义导出 excel、xml、pdf、csv

    它们通常用于封装业务逻辑中的数据模型,使得数据能够以面向对象的方式被操作和传递。 接着,我们来看看如何利用反射来操作JavaBean。Java的`java.lang.reflect`包提供了`Class`、`Field`、`Method`等类,用于反射...

    面向CSA算法的片上多核DSP处理器设计.pdf

    在XML到数据库的转换过程中,通过反射机制可以读取XML Schema文档并生成相应的JavaBean对象,这有助于将XML结构映射为面向对象的形式。 2. **DOM4j技术**:DOM4j是一个Java库,用于处理XML文档。它可以解析XML,...

    基于Java的XML解析与反射设计模式.doc

    Java作为面向对象的编程语言,因其动态性、安全性以及丰富的库支持,成为了实现Web服务和XML解析的首选工具。 XML作为一种通用的数据交换格式,其解析方式主要有DOM、SAX和基于库的方法,如XStream。DOM解析器将...

    各种转换,xml,实体bean,动态bean,map等

    JPA(Java Persistence API)和Hibernate是常见的实体Bean管理框架,提供ORM(Object-Relational Mapping)功能,使得开发者可以以面向对象的方式操作数据库。 3. **动态Bean(Dynamic Bean)**: 动态Bean是指在...

    java核心技术 oracle数据库 xml

    4. **DOM(文档对象模型)**:解析XML并将其表示为一个对象树,方便程序访问和修改。 5. **SAX(简单API for XML)**:事件驱动的解析方式,适用于处理大型XML文档。 6. **XSLT(可扩展样式表转换语言)**:用于将...

    面向对象java课件

    面向对象编程(Object-Oriented Programming,简称OOP)是Java语言的核心特性,也是现代软件开发中的重要思想。本课程“面向对象java课件”主要针对云大软件学院的学生,旨在教授Java的基本概念和高级特性。 1. **...

    COLLADA DOM

    掌握COLLADA DOM API需要对3D图形学、XML和面向对象编程有一定的了解。开发者可以参考COLLADA官方文档、开源项目和在线教程来学习和实践。通过实际操作,例如创建一个简单的3D场景加载器或编辑器,可以加深对COLLADA...

    xmlbeans-2.5.0

    这个库的核心理念是将XML Schema(XSD)转换为Java类,使得开发者可以使用面向对象的方式来处理XML数据,而无需直接处理XML的低级细节。在"xmlbeans-2.5.0"版本中,提供了对XML数据的强大支持和高效处理。 1. **...

    JavaScript王者归来part.1 总数2

     7.2.3 反射机制--枚举对象属性   7.3 对象的构造   7.3.1 构造函数--一个双精度浮点数封装类的例子   7.3.2 缺省构造和拷贝构造   7.3.3 对象常量   7.4 对象的销毁和存储单元的回收   7.5 JavaScript...

    02-java语言进阶源码

    XML是一种通用的数据交换格式,Java提供了DOM、SAX和StAX等多种解析XML的方式。 通过深入研究这些源码,你可以深化对Java语言的理解,提高编程技巧,为解决实际问题打下坚实基础。无论你是初学者还是经验丰富的...

    ssh2常用的jar包解释

    7. **dom4j.jar**: 这是一个高效的XML处理库,Hibernate使用它来读写XML配置文件。dom4j提供了易于使用的API,使得处理XML文档变得简单。 8. **odmg.jar**: ODMG是对象数据管理组制定的ORM规范,Hibernate实现了这...

    JAVA面试题集 (含一些jsp,xml,J2EE,MVC)

    5. **XSLT**:转换XML文档的工具,实现数据的格式化和重排。 **J2EE(Java 2 Platform, Enterprise Edition)** J2EE是Java企业级应用的平台,包含一系列服务、API和协议。面试中可能涉及: 1. **EJB(Enterprise...

    hibernate 3.3 jar包

    例如,JDBC驱动用于与各种数据库进行通信,log4j提供日志记录服务,DOM4J或JAXB等库用于处理XML配置文件。这些库的完整性和版本匹配性对于Hibernate的正常工作至关重要。 在使用Hibernate 3.3时,开发者需要配置`...

    java基础复习笔记(第一阶段)

    学习DOM、SAX和StaX等解析XML的方法,以及JAXB进行对象到XML和XML到对象的转换。 9. **JSON处理**:JSON(JavaScript Object Notation)轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成。熟悉...

    方立勋JavaWeb视频前十一天笔记word版本

    DOM、SAX和DOM4J是三种主要的XML解析技术,各有特点,适用于不同场景。 **7.34 Tip:XML解析技术概述** DOM(Document Object Model)是一种将XML文档转换为树状结构的模型,适合处理小到中型的XML文档。SAX...

    中间件实现异构数据库读取

    - **Java作为开发语言**:Java是一种面向对象的编程语言,具有良好的跨平台能力,能够轻松地在不同的操作系统上运行。使用Java开发中间件,可以确保系统的稳定性和兼容性。 #### 四、中间件的关键组件与工作原理 ...

    java学习线路

    * XML 进阶:DOM、SAX 和 JAXP、dom4j、JDOM 等工具、XQuery 和XQJ、基于 XML 的数据交换 五、Web Service * JAX_WS2、SAAJ 规范、WSDL 和 SOAP 协议、CXF框架、拦截器、CXF 整合 Spring 六、Java Web 编程 * ...

Global site tag (gtag.js) - Google Analytics