基于dom4j编写的xml数据源操作类

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+"]";
}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值