package test; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintWriter; import java.lang.reflect.Field; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; 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; /** * 基于dom4j编写的xml数据源操作类,<p>可以将一个对象组织到xml文件中, * 如: outputDocUTF8ToFile(CreateXmlBaseObjectArray(person),"test.xml");</p><p> * 也可以将该xml中的内容读出来,并根据其中内容生成相应的对象, * 如: Object[] personFromXml = getObjectFromXml("test.xml");</p> * @author qihigh 2010.12.17 * */ public class XmlMethodByDom4j { public static void main(String args[]) throws Throwable{ Student[] person = {new Student("用户名",20,"爷们","春哥纯爷们","扩展"), new Student("第二",25,"爷们c","春哥纯爷们","扩展2")}; outputDocUTF8ToFile(CreateXmlBaseObjectArray(person),"test.xml"); Object[] personFromXml = getObjectFromXml("test.xml"); for(Object personXml : personFromXml){ System.out.println(((Student) personXml).getUserName()+personXml); } } /** * 把一个object数组写成xml形式 * @param objs * @return objcet构造的xml整体的document */ public static Document CreateXmlBaseObjectArray(Object[] objs){ if(objs.length == 0 || objs == null){ return null; } Document doc = DocumentHelper.createDocument(); //根节点 采用的第一个对象的class的name(其实所有的都一样) //当用objs.getClass()时候节点为 <[Ltest.Person;s> Element root = doc.addElement(objs[0].getClass().getName()+"s"); for(Object o : objs){ CreateXmlNode(o,root); } return doc; } /** * 在给定的root 下构造整个obj xml树。 * @param 构建xml基于的obj * @param 要构建的root */ private static void CreateXmlNode(Object obj,Element root){ if(obj != null && !"".equals(obj)){ //获取这个对象的所有属性(person 的所有属性) Map<String,String> attMap = getAttributeMap(obj); //节点属性 String nodeClassName = obj.getClass().getName();//类的全称test.student String[] nodeNameDetail = nodeClassName.split("[.]");//类的全称详细描述数组.用的正则表达式 String nodeName = nodeNameDetail[nodeNameDetail.length-1];//类的名字,比如student //节点的名字为类的名字,紧跟属性为类的全称 Element studentName = root.addElement(nodeName).addAttribute("class", nodeClassName); //节点内部属性 for(String key:attMap.keySet()){ String value = attMap.get(key); Element tempEle = studentName.addElement(key); tempEle.setText(value); } } } /** 输出doc到标准输出流GBK,不好用 还是utf8 */ public static void outputDocGBK(Document doc){ if(doc == null || "".equals(doc)) throw new NullPointerException("doc内容不能为空"); outputDoc(doc,"GBK"); } /** 输出doc到标准输出流UTF8 */ public static void outputDocUTF8(Document doc){ if(doc == null || "".equals(doc)) throw new NullPointerException("doc内容不能为空"); outputDoc(doc,"UTF-8"); } /** 输出doc到标准输出流UTF8到文件 */ public static void outputDocUTF8ToFile(Document doc,String fileName){ if(doc == null || "".equals(doc)) throw new NullPointerException("doc内容不能为空"); outputDocToFile(doc,"UTF-8",fileName); } /** 输出doc到标准输出流 */ private static void outputDoc(Document doc,String formatWay){ try{ OutputFormat format = new OutputFormat(" ",true); format.setEncoding(formatWay); XMLWriter xmlWriter = new XMLWriter(new PrintWriter(System.out),format); xmlWriter.write(doc); xmlWriter.close(); }catch (IOException e) { e.printStackTrace(); } } /** * 输出到文件 */ private static void outputDocToFile(Document doc,String formatWay,String fileName){ try{ OutputFormat format = new OutputFormat(" ",true); format.setEncoding(formatWay); BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File(fileName))); XMLWriter xmlWriter = new XMLWriter(new PrintWriter(bos),format); xmlWriter.write(doc); xmlWriter.close(); }catch (IOException e) { e.printStackTrace(); } } /** * 判断一个对象是否实现了某个特定的接口 * @param theClass Class * @param theInterface String * @return 实现了这个接口返回true */ public static boolean isRealizeInterface(Class theClass,String theInterface){ Class<?>[] classes = theClass.getInterfaces(); for(Class c : classes){ if(c.getName().equals(theInterface)){ return true; } } return false; } /** * 获取给定obj的所有的变量和变量的名称 * @param obj * @return Map<变量名,变量值> */ public static Map<String,String> getAttributeMap(Object obj) { if(obj == null || "".equals(obj)) return null; Map<String,String> attributeMap = new HashMap<String, String>(); Field[] fields = obj.getClass().getDeclaredFields(); for(Field field:fields){ // 对于每个属性,获取属性名 String varName = field.getName(); try{ //获取原来的访问控制权限 boolean accessFlag = field.isAccessible(); //修改之 field.setAccessible(true); //获取对象field 中varName 属性的值 Object value = field.get(obj); // System.out.println("对象中包含的变量:" + varName + " = " + value); //恢复访问权限 field.setAccessible(accessFlag); attributeMap.put(varName, String.valueOf(value));//将任意可转换的类型转换为String }catch (Exception e) { e.printStackTrace(); } } return attributeMap; } /** * 获取xml文件的根节点 * @param xmlFileName * @return xml文件的根节点 * @throws Throwableo */ public static Element getRootFromXml(String xmlFileName) throws Throwable{ SAXReader reader = new SAXReader(); Document doc = reader.read(new File(xmlFileName)); Element elementRoot = doc.getRootElement();//获取根元素 return elementRoot; } /** * 读取一个xml下的属性和节点的方法 * @throws Throwable */ public static Map<String,ElementAtt> readInfo(String fileName) throws Throwable{ if(fileName == null || "".equals(fileName)){ throw new FileNotFoundException("文件名不能为空"); } SAXReader reader = new SAXReader(); Document doc = reader.read(new File(fileName)); Element elementRoot = doc.getRootElement();//获取根元素 最底层的元素 Map<String,ElementAtt> rootMap = new HashMap<String, ElementAtt>(); //迭代器:取根元素下的子元素名称 Iterator<Element> iter = elementRoot.elementIterator(); System.out.println("取根元素下的子元素名称"); int eleBaseCount = 0; Element elebase = null; while(iter.hasNext()){ elebase = iter.next(); eleBaseCount++; String eleName = elebase.getName();//获取元素名称 String eleValue = elebase.attributeValue("class");//获取元素某项属性 这里指定为class属性 System.out.println(eleName + "=" + eleValue); Map<String, String> eleMap = getInfo(elebase); //节点名字可能相同,比如都是student,加个count区别 rootMap.put(eleName+eleBaseCount,new ElementAtt(eleValue,eleMap));//将一个节点包装起来,Map中每一项都是一个完整类的全部属性 } return rootMap; } /** * 通过一个root 获取所有的 递归调用 * 并添加到map中 * @param root */ public static Map<String,String> getInfo(Element root){ Map<String,String> infoMap = new HashMap<String, String>();//用来存贮所有当前节点的子属性以及子属性的map Iterator<Element> iter = root.elementIterator();//遍历root的element int childCount = 0;//用来指明子属性的map并计数 while(iter.hasNext()){ Element element = iter.next(); String eleName = element.getName();//获取元素名称 String eleValue = element.getText();//获取元素值 // System.out.println(eleName + " " + eleValue); infoMap.put(eleName, eleValue); /** 对于有特殊属性的节点(将属性写成<student class="test" >)时要获取class会用到的操作 */ // Iterator<Attribute> iter1 = element.attributeIterator(); // System.out.println("获取属性名称、值"); // while (iter1.hasNext()) { // Attribute elAtt = iter1.next(); // String elAttName = elAtt.getName(); // String elAttValue = elAtt.getValue();//获取属性名称和值 // System.out.println(elAttName+" "+elAttValue); // } /** 没有实现,对于当前需求来说, 也没有什么用 目前只需要一层结构 * (The method put(String, String) in the type Map<String,String> is not applicable for the arguments (String, Map<String,String>)) */ // Map<String,String> childMap = getInfo(element);//自己调用自己 递归方法 // if(childMap != null){ // infoMap.put("child"+childCount, childMap); // } } return infoMap; } /** * 从xml文件中读出内容并对其进行实例化,返回实例化之后的数组(该类必须存在才行) * @throws Throwable */ public static Object[] getObjectFromXml(String fileName) throws Throwable{ /** 从文件读取一个xml下的属性和节点的方法 */ Map<String,ElementAtt> xmlMap = readInfo(fileName); Object[] objectFromXml = new Object[xmlMap.keySet().size()]; int index = 0; for(String eleBase : xmlMap.keySet()){ ElementAtt elementAtt = xmlMap.get(eleBase); String className = elementAtt.getEleValue(); objectFromXml[index] = (Object) createObjectByMap(elementAtt.getEleMap(),Class.forName(className).newInstance()); index++; } return objectFromXml; } /** * 对一个对象中的各个属性进行赋值,值的来源来自于attributeMap * @throws NoSuchFieldException * @throws SecurityException * @throws IllegalAccessException * @throws IllegalArgumentException */ public static Object createObjectByMap(Map<String,String> aMap,Object aObj) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException{ // Field[] fields = aObj.getClass().getDeclaredFields(); for(String attName : aMap.keySet()){ Field field = aObj.getClass().getDeclaredField(attName); //获取原来的访问控制权限 boolean accessFlag = field.isAccessible(); //修改之 field.setAccessible(true); //根据不同的类型注入值 if(field.getType().getName().equals("int")){ //System.out.println("如果是int类型"); field.set(aObj, Integer.valueOf(aMap.get(attName))); }else{ field.set(aObj, aMap.get(attName)); } //恢复访问权限 field.setAccessible(accessFlag); } return aObj; } } /** * 存贮base节点的相关属性 eleValue 包含了该节点标识的类名,eleMap是具体的属性 * @author qihigh * */ class ElementAtt { public ElementAtt(String eleValue, Map<String, String> eleMap) { this.eleValue = eleValue; this.eleMap = eleMap; } private String eleValue; private Map<String, String> eleMap; public String getEleValue() { return eleValue; } public void setEleValue(String eleValue) { this.eleValue = eleValue; } public Map<String, String> getEleMap() { return eleMap; } public void setEleMap(Map<String, String> eleMap) { this.eleMap = eleMap; } @Override public String toString() { return "[eleValue = "+eleValue+" eleMap = "+eleMap+"]"; } } /** * 数据持久化对象 * @author qihigh * */ class Student{ private String userName; private int age; private String sex; private String selfDescription; private String extend; public Student(){} public Student(String userName, int age, String sex, String selfDescription,String extend) { this.userName = userName; this.age = age; this.sex = sex; this.selfDescription = selfDescription; this.extend = extend; } public String getUserName() { return userName; } @Override public String toString(){ return "[userName= "+userName+";age="+age+";sex="+sex+";selfDescription="+selfDescription+"]"; } }