工作中遇到了两种不同表单设计器保存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:[email protected]">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");
}
}