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().substring(5)), 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");//源文件的标签名和实体bean类名的映射itemMap.put("label", "Label");itemMap.put("line", "Line");itemMap.put("textfield", "Textfield");}/** * * @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++){ 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())){String text = element.getText();if(text.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()));}}}/** * * @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");}}