Android之XML生成与解析工具——XmlSerializer

         开发Android项目时会遇到各种数据的存储与获取,然而保存数据的方式有很多中,例如SQlite数据库、网络服务、XML、文件流等。在面向对象开发的人员肯定偏向于封装数据模型为对象进行反射等操作获取信息,这就需要编写一些特定场合下的工具类了。本人在开发一款医疗APP时就遇到将XML格式的数据保存到客户端本地,需要时再进行解析。这里就总结下XML的生成与解析工具的编写。

将数据(即数据模型)传入工具类,工具类根据对象模型生成XML文件,代码如下:

/**
	 * 根据List<对象模型>生成XML
	 * 
	 * @param list
	 *            List<对象模型>
	 * @param xmlPath
	 *            xml文件保存路径
	 * @param xmlName
	 *            xml文件名称
	 * @param classesName
	 *            对象集合名称
	 * @param codeType
	 *            编码格式
	 * @param <T>
	 * @return
	 */
	public static <T> boolean parse(List<T> list, String xmlPath,String xmlName, String classesName, String codeType) {
		if (list == null || list.size() <= 0) {
			return false;
		}
		File file = null;
		if (xmlPath == null || "".equals(xmlPath)) {
			file = new File(Environment.getExternalStorageDirectory(),xmlName);// SD卡路径
		} else {
			file = new File(xmlPath, xmlName);
		}
		final String className = list.get(0).getClass().getSimpleName();
		classesName = classesName == null ? className + "s" : classesName;
		codeType = codeType == null ? "utf-8" : codeType;
		XmlSerializer serializer = Xml.newSerializer();// xml文件生成器
		FileOutputStream fos = null;
		try {
			fos = new FileOutputStream(file);
			// 为xml生成器设置输出流和字符编码
			serializer.setOutput(fos, codeType);
			// 开始文档,参数分别为字符编码和是否保持独立
			serializer.startDocument(codeType, true);
			// 开始标签,参数分别为:命名空间和标签名
			serializer.startTag(namespace, classesName);
			for (Object obj : list) {
				serializer.startTag(namespace, className);
				Field fields[] = obj.getClass().getDeclaredFields();
				for (Field field : fields) {
					final String fieldName = field.getName();
					field.setAccessible(true);
					serializer.startTag(namespace, fieldName);
					serializer.text(String.valueOf(field.get(obj)));
					serializer.endTag(namespace, fieldName);
				}
				serializer.endTag(namespace, className);
			}
			serializer.endTag(namespace, classesName);
			serializer.endDocument();// 结束xml文档
			return true;
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				fos.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return false;
	}
读取XML的方法如下:

/**
	 * 根据对象模型解析XML
	 * 
	 * @param c
	 *            对象模型
	 * @param xmlPath
	 *            xml文件保存路径
	 * @param xmlName
	 *            xml文件名称
	 * @param classesName
	 *            对象集合名称
	 * @param codeType
	 *            编码格式
	 * @param <T>
	 * @return
	 */
	public static <T> List<T> pullXml(Class<T> c,String xmlPath,String xmlName,String classesName,String codeType) {
		FileInputStream fis = null;
		try {
            File file = null;
            if(xmlPath == null || "".equals(xmlPath)){
                file = new File(Environment.getExternalStorageDirectory(),xmlName);// SD卡路径
            }else{
                file = new File(xmlPath,xmlName);
            }
            final String className = c.getSimpleName();
            classesName = classesName == null ? className+"s" : classesName;
            codeType = codeType == null ? "utf-8" : codeType;
            List<T> list = null;
            T t = null;
            Object obj = Class.forName(c.getName()).newInstance();
            Field[] fields = obj.getClass().getDeclaredFields();
            XmlPullParser parser = Xml.newPullParser();// 获取xml解析器
            fis = new FileInputStream(file);
            parser.setInput(fis, codeType);// 参数分别为输入流和字符编码
            int type = parser.getEventType();
            while (type != XmlPullParser.END_DOCUMENT) {// 如果事件不等于文档结束事件就继续循环
                switch (type) {
                    case XmlPullParser.START_TAG:
                        if (classesName.equals(parser.getName())) {
                            list = new ArrayList<T>();
                        } else if (className.equals(parser.getName())) {
                            t = c.newInstance();
                        } else {
                            setField(t,fields,parser.getName(),parser.nextText());
                        }
                        break;
                    case XmlPullParser.END_TAG:
                        if (className.equals(parser.getName())) {
                            list.add(t);
                            t = null;
                        }
                        break;
                }
                type = parser.next();// 继续下一个事件
            }
            return list;
        } catch (NumberFormatException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (XmlPullParserException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
			try {
				fis.close();
			}catch (Exception e){
				e.printStackTrace();
			}
		}
		return null;
    }

读取XML生成数据模型时需要通过JAVA的反射机制进行对象模型的赋值,下面就是赋值的方法:

/**
     * 设置成员变量值
     * @param t 泛型对象
     * @param fields 成员变量集合
     * @param nodeName 节点名称
     * @param nodeValue 节点值
     * @param <T>
     * @throws Exception
     */
    private static <T> void setField(T t,Field[] fields,String nodeName,String nodeValue) throws Exception {
        for (Field field : fields) {
            final String fieldName = field.getName();
            if (fieldName.equals(nodeName)) {
                final Class<?> type = field.getType();
                field.setAccessible(true);
                if (type.equals(String.class)) {
                    field.set(t, nodeValue);
                }else if(type.equals(int.class) || type.equals(Integer.class)){
                    field.set(t, Integer.parseInt(nodeValue));
                }else if(type.equals(boolean.class) || type.equals(Boolean.class)){
                    field.set(t, "1".equals(nodeValue) || "true".equals(nodeValue));
                }else if(type.equals(long.class) || type.equals(Long.class)){
                    field.set(t, Long.parseLong(nodeValue));
                }else if(type.equals(double.class) || type.equals(Double.class)){
                    field.set(t, Double.parseDouble(nodeValue));
                }else if(type.equals(float.class) || type.equals(Float.class)){
                    field.set(t, Float.parseFloat(nodeValue));
                }
            }
        }
    }

由此就可以完成XML的解析与生成了,为了方便使用扩展了一些多态方法。下面贴出完整代码:



import android.os.Environment;
import android.util.Xml;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

/**
 * *********************************************
 * 
 * File name: XmlParse.java
 * 
 * @Author: zhsf @version: 1.0 @Date: 2015-6-24
 * @Description: XML文件生成与解析工具类:支持对象与集合的生成与解析
 * 
 *Others:
 * 
 *Function List:
 * 
 *History:
 * 
 **********************************************
 */

public class XmlParse {
	
	private final static String namespace = null;// 命名空间

	/**
	 * 根据单个对象模型生成XML
	 * 
	 * @param clazz
	 *            对象模型
	 * @param xmlName
	 *            xml文件名称
	 * @param <T>
	 * @return
	 */
	public static <T> boolean parseSingle(T clazz, String xmlName) {
		List<T> list = new ArrayList<T>();
		list.add(clazz);
		return parse(list, null, xmlName, null, null);
	}

	/**
	 * 根据单个对象模型生成XML
	 * 
	 * @param clazz
	 *            对象模型
	 * @param xmlName
	 *            xml文件名称
	 * @param classesName
	 *            对象集合名称
	 * @param codeType
	 *            编码格式
	 * @param <T>
	 * @return
	 */
	public static <T> boolean parseSingle(T clazz, String xmlName,
			String classesName, String codeType) {
		List<T> list = new ArrayList<T>();
		list.add(clazz);
		return parse(list, null, xmlName, classesName, codeType);
	}

	/**
	 * 根据List<对象模型>生成XML
	 * 
	 * @param list
	 *            List<对象模型>
	 * @param xmlName
	 *            xml文件名称
	 * @param <T>
	 * @return
	 */
	public static <T> boolean parse(List<T> list, String xmlName) {
		return parse(list, null, xmlName, null, null);
	}

	/**
	 * 根据List<对象模型>生成XML
	 * 
	 * @param list
	 *            List<对象模型>
	 * @param xmlPath
	 *            xml文件保存路径
	 * @param xmlName
	 *            xml文件名称
	 * @param <T>
	 * @return
	 */
	public static <T> boolean parse(List<T> list, String xmlPath, String xmlName) {
		return parse(list, xmlPath, xmlName, null, null);
	}

	/**
	 * 根据List<对象模型>生成XML
	 * 
	 * @param list
	 *            List<对象模型>
	 * @param xmlPath
	 *            xml文件保存路径
	 * @param xmlName
	 *            xml文件名称
	 * @param classesName
	 *            对象集合名称
	 * @param codeType
	 *            编码格式
	 * @param <T>
	 * @return
	 */
	public static <T> boolean parse(List<T> list, String xmlPath,String xmlName, String classesName, String codeType) {
		if (list == null || list.size() <= 0) {
			return false;
		}
		File file = null;
		if (xmlPath == null || "".equals(xmlPath)) {
			file = new File(Environment.getExternalStorageDirectory(),xmlName);// SD卡路径
		} else {
			file = new File(xmlPath, xmlName);
		}
		final String className = list.get(0).getClass().getSimpleName();
		classesName = classesName == null ? className + "s" : classesName;
		codeType = codeType == null ? "utf-8" : codeType;
		XmlSerializer serializer = Xml.newSerializer();// xml文件生成器
		FileOutputStream fos = null;
		try {
			fos = new FileOutputStream(file);
			// 为xml生成器设置输出流和字符编码
			serializer.setOutput(fos, codeType);
			// 开始文档,参数分别为字符编码和是否保持独立
			serializer.startDocument(codeType, true);
			// 开始标签,参数分别为:命名空间和标签名
			serializer.startTag(namespace, classesName);
			for (Object obj : list) {
				serializer.startTag(namespace, className);
				Field fields[] = obj.getClass().getDeclaredFields();
				for (Field field : fields) {
					final String fieldName = field.getName();
					field.setAccessible(true);
					serializer.startTag(namespace, fieldName);
					serializer.text(String.valueOf(field.get(obj)));
					serializer.endTag(namespace, fieldName);
				}
				serializer.endTag(namespace, className);
			}
			serializer.endTag(namespace, classesName);
			serializer.endDocument();// 结束xml文档
			return true;
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				fos.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return false;
	}

	/**
	 * 根据对象模型解析XML
	 * 
	 * @param c
	 *            对象模型
	 * @param xmlName
	 *            xml文件名称
	 * @param <T>
	 * @return
	 */
	public static <T> List<T> pullXml(Class<T> c, String xmlName) {
		return pullXml(c, null, xmlName, null, null);
	}

	/**
	 * 根据对象模型解析XML
	 * 
	 * @param c
	 *            对象模型
	 * @param xmlPath
	 *            xml文件保存路径
	 * @param xmlName
	 *            xml文件名称
	 * @param <T>
	 * @return
	 */
	public static <T> List<T> pullXml(Class<T> c, String xmlPath, String xmlName) {
		return pullXml(c, xmlPath, xmlName, null, null);
	}

	/**
	 * 根据对象模型解析XML
	 * 
	 * @param c
	 *            对象模型
	 * @param xmlPath
	 *            xml文件保存路径
	 * @param xmlName
	 *            xml文件名称
	 * @param classesName
	 *            对象集合名称
	 * @param codeType
	 *            编码格式
	 * @param <T>
	 * @return
	 */
	public static <T> List<T> pullXml(Class<T> c,String xmlPath,String xmlName,String classesName,String codeType) {
		FileInputStream fis = null;
		try {
            File file = null;
            if(xmlPath == null || "".equals(xmlPath)){
                file = new File(Environment.getExternalStorageDirectory(),xmlName);// SD卡路径
            }else{
                file = new File(xmlPath,xmlName);
            }
            final String className = c.getSimpleName();
            classesName = classesName == null ? className+"s" : classesName;
            codeType = codeType == null ? "utf-8" : codeType;
            List<T> list = null;
            T t = null;
            Object obj = Class.forName(c.getName()).newInstance();
            Field[] fields = obj.getClass().getDeclaredFields();
            XmlPullParser parser = Xml.newPullParser();// 获取xml解析器
            fis = new FileInputStream(file);
            parser.setInput(fis, codeType);// 参数分别为输入流和字符编码
            int type = parser.getEventType();
            while (type != XmlPullParser.END_DOCUMENT) {// 如果事件不等于文档结束事件就继续循环
                switch (type) {
                    case XmlPullParser.START_TAG:
                        if (classesName.equals(parser.getName())) {
                            list = new ArrayList<T>();
                        } else if (className.equals(parser.getName())) {
                            t = c.newInstance();
                        } else {
                            setField(t,fields,parser.getName(),parser.nextText());
                        }
                        break;
                    case XmlPullParser.END_TAG:
                        if (className.equals(parser.getName())) {
                            list.add(t);
                            t = null;
                        }
                        break;
                }
                type = parser.next();// 继续下一个事件
            }
            return list;
        } catch (NumberFormatException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (XmlPullParserException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
			try {
				fis.close();
			}catch (Exception e){
				e.printStackTrace();
			}
		}
		return null;
    }


    /**
     * 设置成员变量值
     * @param t 泛型对象
     * @param fields 成员变量集合
     * @param nodeName 节点名称
     * @param nodeValue 节点值
     * @param <T>
     * @throws Exception
     */
    private static <T> void setField(T t,Field[] fields,String nodeName,String nodeValue) throws Exception {
        for (Field field : fields) {
            final String fieldName = field.getName();
            if (fieldName.equals(nodeName)) {
                final Class<?> type = field.getType();
                field.setAccessible(true);
                if (type.equals(String.class)) {
                    field.set(t, nodeValue);
                }else if(type.equals(int.class) || type.equals(Integer.class)){
                    field.set(t, Integer.parseInt(nodeValue));
                }else if(type.equals(boolean.class) || type.equals(Boolean.class)){
                    field.set(t, "1".equals(nodeValue) || "true".equals(nodeValue));
                }else if(type.equals(long.class) || type.equals(Long.class)){
                    field.set(t, Long.parseLong(nodeValue));
                }else if(type.equals(double.class) || type.equals(Double.class)){
                    field.set(t, Double.parseDouble(nodeValue));
                }else if(type.equals(float.class) || type.equals(Float.class)){
                    field.set(t, Float.parseFloat(nodeValue));
                }
            }
        }
    }

}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用Pull解析生成XML文件的一般步骤如下: 1. 创建一个XmlSerializer对象,该对象将用于序列化XML数据。 2. 使用XmlSerializer对象创建一个XmlWriter对象,该对象将用于将XML数据写入文件。 3. 使用XmlWriter对象的WriteStartDocument方法写入XML文件的开头。 4. 使用XmlWriter对象的WriteStartElement方法写入根元素的开始标记。 5. 使用XmlWriter对象的WriteElementString方法写入子元素的标记和值。 6. 使用XmlWriter对象的WriteEndElement方法写入根元素的结束标记。 7. 使用XmlWriter对象的WriteEndDocument方法写入XML文件的结尾。 8. 关闭XmlWriter对象。 下面是一个使用Pull解析生成XML文件的示例代码: ``` java import java.io.FileWriter; import javax.xml.stream.XMLOutputFactory; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamWriter; public class XmlGenerator { public static void main(String[] args) { try { // 创建一个XMLOutputFactory对象 XMLOutputFactory outputFactory = XMLOutputFactory.newInstance(); // 创建一个XMLStreamWriter对象 XMLStreamWriter writer = outputFactory .createXMLStreamWriter(new FileWriter("output.xml")); // 写入XML文件的开头 writer.writeStartDocument(); // 写入根元素的开始标记 writer.writeStartElement("root"); // 写入子元素的标记和值 writer.writeStartElement("child"); writer.writeCharacters("Hello World!"); writer.writeEndElement(); // 写入根元素的结束标记 writer.writeEndElement(); // 写入XML文件的结尾 writer.writeEndDocument(); // 关闭XMLStreamWriter对象 writer.close(); System.out.println("XML文件已生成!"); } catch (Exception e) { e.printStackTrace(); } } } ``` 执行该代码后,将在项目根目录下生成名为"output.xml"的XML文件,其内容如下: ``` xml <?xml version="1.0" ?> <root> <child>Hello World!</child> </root> ``` 注意:上述示例代码中使用的是Java语言的StAX API,而不是Pull解析器。不过,StAX API提供了一种类Pull解析器的编程模型,可以方便地生成XML文件。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值