xml操作工具分享-实现篇

  前面介绍了xml工具实现了哪些功能,本文现在一一介绍实现的代码,程序绝对可用,如有bug,

谢谢告知,希望能一同完善这个工具。

   本工具实现的原理步骤是:

   1)  定义一个带有特定注释的javabean类,

   2)  工具类xmlutil利用在javabean类的注释反射完成javabean的属性值更新或者xml的dom树的组装。

(下面的代码本想以附件的方式上传的,但是本人刚用csdn不久还未找到能上传附件,真遗憾!)

现在给出主要的完整的代码,

 

   1) 带有特定注释的javabean类如下,Student.java

 import XMLHandler.xmlopt.annotation.Ignore; import XMLHandler.xmlopt.annotation.Node; import XMLHandler.xmlopt.annotation.Xml; import XMLHandler.xmlopt.annotation.Attr; /** * @author -ziliang * * @desc-定义需要处理的javabean * * */ //xml标示生成的xml字符串的根节点名 @Xml(name="Student") public class Student { private String id; private String name; private String bir; private String age; private String service; public String getId() { return id; } /** * 注释node的代码在后面给出,其name属性对应xml节点名, * name如不给出,xml文档的节点名默认取属性名 * */ @Node(name="ID") public void setId(String id) { this.id = id; } public String getName() { return name; } @Node(name="NAME") public void setName(String name) { this.name = name; } public String getBir() { return bir; } @Node(name="BIR") public void setBir(String bir) { this.bir = bir; } public String getAge() { return age; } /** * 注释@Attr的代码在后面给出,其name属性对应xml节点的属性, * name如不给出,xml属性节点名默认取值为javabean的属性名 * */ @Attr(name="age") public void setAge(String age) { this.age = age; } public String getService() { return service; } /** * 注释@Ignore的代码在后面给出,表示在生成xml文档时忽略此属性, * 但这个节点可能处理业务是有用的,所以javabean保留此属性 * */ @Ignore public void setService(String service) { this.service = service; } }  

 

 

下面给出几个注释的定义

 Attr.java的定义

import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Description: 标记xml为节点属性 * Create DateTime: 2011-1-15 * * @author ziliang */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited public @interface Attr { /** * 和xml下 对应节点的名称 * * @return */ public String name() default ""; }

Node.java的定义

import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Title: 标记该属性为xml的一个节点 * Description: * Create DateTime: 2011-1-15 * * @author ziliang */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited public @interface Node { /** * 和xml下 对应节点的名称 * * @return */ public String name() default ""; /** * 如果为集合类对象, 对应集合类型内存放的class * * @return */ public Class<?> ClassType() default Object.class; }

Ignore.java的定义

import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Title: 标记该属性不会被映射 * Description: * Create DateTime: 2011-1-15 * * @author ziliang */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited public @interface Ignore { }

Xml.java的定义

import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * @desc: 标记为xml * @date-2011-1-15 * @author ziliang */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited public @interface Xml { /** * xml根节点名 * * @return */ public String name() default ""; /** * xml的命名空间 * * @return */ public String qName() default ""; }   

 

 

 下面就是工具类,

 

import java.io.*; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.*; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.DocumentHelper; import org.dom4j.Element; import org.dom4j.Namespace; import org.dom4j.QName; import org.dom4j.io.SAXReader; import XMLHandler.xmlopt.annotation.*; /** * @desc: 操作xml的工具类 * @date: 2011-1-28 * @author ziliang */ public class XmlUtil { /** * 生成xml主调的方法 */ public static String createXml(Object target) { //用到了递归调用 return createElement(target).asXML(); } /** * 根据xml转对象的主调方法 * */ public static Object createTarget(String xml, Object target, String trunc_exp) throws UnsupportedEncodingException { InputStream in = new ByteArrayInputStream(xml.getBytes()); Object res = null; try { //用到了递归调用 res = createTarget(in, target, trunc_exp); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (DocumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } return res; } /** * 构建xml文档 * */ public static Element createElement(Object target) { Class<?> targetClass = target.getClass(); // 取类上的document注解,得到name属性,用name属性做xml根节点 Xml docAnno = targetClass.getAnnotation(Xml.class); if (docAnno == null) { throw new RuntimeException("被映射的类必须带有annotation的注解"); } // 取文档根节点名字,如名字注释空则默认取类名 String docName = docAnno.name(); if (docName == null || docName.length() == 0) docName = target.getClass().getSimpleName(); // 构建文档根节点 Element element = DocumentHelper.createElement(docName); // xml文档名称空间 String qName = docAnno.qName(); if (qName != null && qName.length() != 0) element.setQName(new QName(docName, new Namespace(null, qName))); // 循环javabean的类的set方法 Method methods[] = targetClass.getMethods(); for (Method method : methods) { if (!isSetMethod(method)) continue; if (method.getAnnotation(Ignore.class) != null) continue; // 获取方法的参数类型 Class<?> attrType = method.getParameterTypes()[0]; // 如果注释没有name属性,则将属性的set方法去掉'set'作为节点名称 String defaultNodeName = method.getName().substring(3); // 属性对应的get方法得到属性值 Object value = invokeGet(target, defaultNodeName); if (value == null) value = ""; // 取得bean节点上的注释 Node nodeAnno = method.getAnnotation(Node.class); // 取得bean属性上的注释 Attr attrAnno = method.getAnnotation(Attr.class); // 参数为简单类型,直接处理即可 if (isSimpleAttr(attrType)) { String name = null;// 节点名称 // 生成javabean的属性节点 if (attrAnno != null) { name = attrAnno.name(); if (!isNotEmpty(name)) name = defaultNodeName; element.addAttribute(name, value.toString()); continue; } // 生成javabean节点 if (nodeAnno != null) { name = nodeAnno.name(); if (!isNotEmpty(name)) name = defaultNodeName; Element e = element.addElement(name); e.setText(value.toString()); } continue; } // 复合类型(主要是指javabean含有list成员的情况)递归处理 if (isCollection(attrType)) { String name = nodeAnno.name(); if (name == null || name.length() == 0) name = defaultNodeName; Element e = null; if (nodeAnno.surround()) { e = element.addElement(name); } else { e = element; } if (value == null) { continue; } Collection<?> collection = (Collection<?>) value; for (Object object : collection) { Element se = createElement(object); e.add(se); } continue; } // javaBean 递归调用自身 Element e = createElement(value); element.add(e); }// set-method return element; } public static Object createTarget(InputStream in, Object target, String trunc_exp) throws DocumentException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, InstantiationException, UnsupportedEncodingException { SAXReader reader = new SAXReader(); InputStreamReader strInStream = new InputStreamReader(in, "GBK"); org.dom4j.Document document = reader.read(strInStream); Class<?> targetClass = target.getClass(); // 得到类上的document注解 Xml docAnno = targetClass.getAnnotation(Xml.class); if (docAnno == null) { throw new RuntimeException("被映射的类必须带annotation注解"); } String rootName = targetClass.getSimpleName(); if (docAnno.name() != null && docAnno.name().length() != 0) { rootName = docAnno.name(); } // 从截取的地方开始转domain org.dom4j.Node rootNode = null; if (trunc_exp == null) { rootNode = document.selectSingleNode(rootName); } else { rootNode = document.selectSingleNode(trunc_exp + rootName); } // org.dom4j.Node rootNode = document.selectSingleNode(rootName); Method methods[] = targetClass.getMethods(); // 处理set方法 for (Method method : methods) { if (!isSetMethod(method)) continue; if (method.getAnnotation(Ignore.class) != null) continue; Class<?> attrType = method.getParameterTypes()[0]; // 如果注解没有name属性,则将属性的set方法名去掉'set'作为xml节点名称 String defaultNodeName = method.getName().substring(3); Node nodeAnno = method.getAnnotation(Node.class); Attr attrAnno = method.getAnnotation(Attr.class); String name = null;// 节点名称 org.dom4j.Node xnode = null; String attr = null;// 节点自身的属性 String node_attr_value = null;// 节点自身的属性值 // NodeType nodeType = null;// 节点类型 if (isSimpleAttr(attrType)) { String value = null; // 处理属性 if (attrAnno != null) { name = attrAnno.name(); if (!isNotEmpty(name)) name = defaultNodeName; xnode = rootNode.selectSingleNode("@" + name); if (xnode == null) continue; value = xnode.getStringValue(); method.invoke(target, value); continue; } // 更新节点 if (nodeAnno != null) { name = nodeAnno.name(); if (!isNotEmpty(name)) name = defaultNodeName; } xnode = rootNode.selectSingleNode(name); if (xnode == null) continue; value = xnode.getText(); Object val = value; if (attrType.isPrimitive()) { val = parse(value, attrType); } method.invoke(target, val); continue; } // 处理List的情况 if (isCollection(attrType)) { @SuppressWarnings("unchecked") Class<?> elementType = nodeAnno.ClassType(); Xml docAnnoXml = elementType.getAnnotation(Xml.class); String classname = docAnnoXml.name(); List<org.dom4j.Node> xnodes = rootNode.selectNodes("//" + name + "/" + classname); @SuppressWarnings("unchecked") Collection<Object> c = (Collection<Object>) createCollection(attrType); for (org.dom4j.Node snode : xnodes) { Object oe = elementType.newInstance(); oe = createTarget(snode.asXML(), oe, trunc_exp); c.add(oe); } method.invoke(target, c); continue; } // 处理bean的情况 xnode = rootNode.selectSingleNode(name); if (xnode == null) continue; Object obj = attrType.newInstance(); obj = createTarget(xnode.asXML(), obj, trunc_exp); method.invoke(target, obj); } return target; } /** * * 下面是xml操作工具的一些辅助方法 * */ /** * 转化封转对象为原始值 * */ private static Object parse(String value, Class<?> attrType) { Object val = null; if (attrType == int.class || attrType == Integer.class) val = Integer.parseInt(value); if (attrType == long.class || attrType == Long.class) val = Long.parseLong(value); if (attrType == double.class || attrType == Double.class) val = Double.parseDouble(value); if (attrType == boolean.class || attrType == Boolean.class) val = Boolean.parseBoolean(value); if (attrType == byte.class || attrType == Byte.class) val = Byte.parseByte(value); return val; } /** * 获取javabean的属性值 * */ private static Object invokeGet(Object target, String name) { name = name.substring(0, 1).toUpperCase() + name.substring(1); String getMethodName = "get" + name; Object res = null; try { Method method = target.getClass().getMethod(getMethodName); res = method.invoke(target); } catch (SecurityException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } return res; } /** * 是否为简单属性 * * @param clazz * @return */ private static boolean isSimpleAttr(Class<?> clazz) { if (clazz.isPrimitive()) return true; if (clazz == String.class) return true; return false; } /** * 是否为集合类 * * @param clazz * @return */ private static boolean isCollection(Class<?> clazz) { return Collection.class.isAssignableFrom(clazz); } /** * 是否为符合javaBean规范的set方法 * * @param methodName * @return */ public static boolean isSetMethod(Method method) { String methodName = method.getName(); if (!methodName.startsWith("set")) { return false; } Class<?>[] clazzes = method.getParameterTypes(); // 如果方法的参数>1 则不是设置属性的方法 if (clazzes.length != 1) { return false; } return true; } /** * 根据类型创建集合 * * @param paramType * @return */ private static Collection<?> createCollection(Class<?> paramType) { if (paramType == List.class) { return new ArrayList<Object>(); } if (paramType == Set.class) { return new HashSet<Object>(); } throw new IllegalArgumentException(paramType.getName() + "不能转化为集合类"); } /** * * 判断是否有set+elmentname方法,并设置对象obj的属性elmentname的值为elmentvalue * * @throws InvocationTargetException * @throws IllegalAccessException * @throws IllegalArgumentException */ public static Object invokeSetMethod(Object obj, String elmentname, String elmentvalue) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException { Class<?> targetClass = obj.getClass(); String m = "set" + FirstUpper(elmentname); Method methods[] = targetClass.getMethods(); for (Method method : methods) { if (method.getName().equals(m)) { method.invoke(obj, elmentvalue); } } return obj; } public static String FirstUpper(String s) { return s.substring(0, 1).toUpperCase() + s.substring(1); } public static boolean isNotEmpty(String s) { return s != null && !s.trim().equalsIgnoreCase(""); } }

     

你可能感兴趣的:(xml,String,object,null,工具,methods)