Android XML小工具
一、概述
XML与Object互相转化,支持8种基本类型、String和byte[]。byte[]需要经由base64编码(API8以后才有,之前版本可以自己拷入)。
更多代码及测试用例,见附件工程!
二、Object –> XML
- public class XmlBuilder {
- /**
- * 由对象属性生成XML
- *
- * @param outs 输出流
- * @param encoding 字符编码
- * @param obj 对象
- */
- public void buildXml(OutputStream outs, String encoding, Object obj)
- throws IllegalArgumentException, IllegalStateException,
- IOException, IllegalAccessException {
- XmlSerializer serializer = Xml.newSerializer(); // 创建一个Xml序列化
- serializer.setOutput(outs, encoding); // 设置输出流及字符编码
- serializer.startDocument(encoding, true); // 开始文档
- writeXml(serializer, obj); // 写文档
- serializer.endDocument(); // 结束文档
- outs.close(); // 关闭输出流
- }
- /**
- * 将对象属性写入XML
- *
- * @param serializer XML序列化
- * @param obj 对象
- */
- private void writeXml(XmlSerializer serializer, Object obj)
- throws IllegalArgumentException, IllegalStateException,
- IOException, IllegalAccessException {
- final String tag_type = "type";
- final String tag_value = "value";
- Class> cls = obj.getClass(); // 获取对象运行时类
- String clsName = cls.getName(); // 获取对象名称
- serializer.startTag(null, clsName);
- Field[] fields = cls.getDeclaredFields(); // 返回类声明的所有字段
- boolean isWrite;
- Class> type; // 变量类型
- String varName, typeName, value = null; // 变量名、类型名、变量值
- for (Field field : fields) {
- isWrite = true;
- type = field.getType(); // 获取变量类型
- typeName = type.getName(); // 获取类型名
- field.setAccessible(true); // 设置变量可访问
- if (type.isPrimitive()) { // 是否为基本类型
- if (typeName.equals("boolean")) {
- value = String.valueOf(field.getBoolean(obj));
- } else if (typeName.equals("char")) {
- // char型未赋值,为默认'\u0000'时,会影响parser.next()
- char c = field.getChar(obj);
- value = c == '\u0000' ? "null" : String.valueOf(field
- .getChar(obj));
- } else if (typeName.equals("byte")) {
- value = String.valueOf(field.getByte(obj));
- } else if (typeName.equals("short")) {
- value = String.valueOf(field.getShort(obj));
- } else if (typeName.equals("int")) {
- value = String.valueOf(field.getInt(obj));
- } else if (typeName.equals("long")) {
- value = String.valueOf(field.getLong(obj));
- } else if (typeName.equals("float")) {
- value = String.valueOf(field.getFloat(obj));
- } else if (typeName.equals("double")) {
- value = String.valueOf(field.getDouble(obj));
- }
- } else if (typeName.equals("java.lang.String")) { // 是否为String
- value = field.get(obj) == null ? "null" : field.get(obj)
- .toString();
- } else if (typeName.equals("[B")) { // 是否为byte[]
- typeName = getTypeHelper(type); // 字符代码->[]形式
- // 用Base64将byte[]转成字符串(SDK 2.2之后自带)
- value = field.get(obj) == null ? "null"
- : Base64.encodeToString((byte[]) field.get(obj),
- Base64.DEFAULT);
- } else { // 其他类型暂不需要
- isWrite = false;
- }
- if (isWrite) {
- varName = field.getName(); // 获取变量名
- serializer.startTag(null, varName);
- writeTag(serializer, tag_type, typeName);
- writeTag(serializer, tag_value, value);
- serializer.endTag(null, varName);
- }
- }
- serializer.endTag(null, clsName);
- }
- /**
- * 字符代码->[]形式
- */
- private String getTypeHelper(Class> type) {
- if (type.isArray()) {
- Class> c = type.getComponentType();
- return getTypeHelper(c) + "[]";
- } else {
- return type.getName();
- }
- }
- /**
- * 写一个标签及值
- */
- private void writeTag(XmlSerializer serializer, String tag, String value)
- throws IllegalArgumentException, IllegalStateException, IOException {
- serializer.startTag(null, tag);
- serializer.text(value);
- serializer.endTag(null, tag);
- }
- }
三、XML -> Object
- public class XmlParser {
- /**
- * 分析XML将对应值赋予对象
- *
- * @param ins 输入流
- * @param encoding 字符编码
- * @param obj 对象
- */
- public void parseXml(InputStream ins, String encoding, Object obj)
- throws XmlPullParserException, IllegalArgumentException,
- UnsupportedEncodingException, IllegalAccessException, IOException {
- XmlPullParser parser = Xml.newPullParser(); // 创建一个Xml分析器
- parser.setInput(ins, encoding); // 设置输入流及字符编码
- parseXml(parser, obj); // 解析文档
- ins.close(); // 关闭输入流
- }
- /**
- * 分析XML详细步骤
- *
- * @param parser Xml分析器
- * @param obj 对象
- */
- private void parseXml(XmlPullParser parser, Object obj)
- throws XmlPullParserException, IllegalArgumentException,
- UnsupportedEncodingException, IllegalAccessException, IOException {
- final String tag_value = "value";
- Class> cls = obj.getClass(); // 获取对象运行时类
- String clsName = cls.getName(); // 获取对象名称
- Field[] fields = cls.getDeclaredFields(); // 返回类声明的所有字段
- Field field = null;
- int tagDepth; // 标签深度
- String tagName; // 标签名称
- int eventType = parser.getEventType(); // 获取事件类型
- while (true) {
- if (eventType == XmlPullParser.START_DOCUMENT) {
- // Log.i("START_DOCUMENT", "=START_DOCUMENT");
- } else if (eventType == XmlPullParser.START_TAG) {
- // Log.i("START_TAG", "=START_TAG");
- tagDepth = parser.getDepth(); // 获取标签深度
- tagName = parser.getName(); // 获取标签名称
- if (tagDepth == 1) { // 一级标签
- if (!tagName.equals(clsName)) { // 与对象名称不一致时
- throw new XmlPullParserException("XML首标签名与对象名称不一致");
- }
- } else if (tagDepth == 2) { // 二级标签
- // 判断标签名称是否符合类的某一字段名称
- field = hasField(tagName, fields);
- } else if (tagDepth == 3 && field != null) { // 三级标签
- if (tagName.equals(tag_value)) { // 如果是value标签
- setValue(obj, field, parser.nextText());
- field = null;
- }
- }
- } else if (eventType == XmlPullParser.END_TAG) {
- // Log.i("END_TAG", "=END_TAG");
- } else if (eventType == XmlPullParser.TEXT) {
- // Log.i("TEXT", "=TEXT");
- } else if (eventType == XmlPullParser.END_DOCUMENT) {
- // Log.i("END_DOCUMENT", "=END_DOCUMENT");
- break;
- }
- eventType = parser.next(); // 下一解析事件
- }
- }
- /**
- * 判断标签名称是否符合类的某一字段名称
- *
- * @param tagName 标签名称
- * @param fields 类字段集合
- * @return 符合:Field;否则:null
- */
- private Field hasField(String tagName, Field[] fields) {
- for (Field field : fields) {
- if (tagName.equals(field.getName())) {
- return field;
- }
- }
- return null;
- }
- /**
- * 给字段设值
- *
- * @param obj 对象
- * @param field 字段
- * @param value 值
- */
- private void setValue(Object obj, Field field, String value)
- throws IllegalArgumentException, IllegalAccessException,
- UnsupportedEncodingException {
- Class> type = field.getType(); // 变量类型
- String typeName = type.getName(); // 类型名
- field.setAccessible(true); // 设置变量可访问
- if (type.isPrimitive()) { // 是否为基本类型
- if (typeName.equals("boolean")) {
- field.setBoolean(obj, Boolean.parseBoolean(value));
- } else if (typeName.equals("char")) {
- if (!value.equals("null")) {
- field.setChar(obj, value.charAt(0));
- }
- } else if (typeName.equals("byte")) {
- field.setByte(obj, Byte.parseByte(value));
- } else if (typeName.equals("short")) {
- field.setShort(obj, Short.parseShort(value));
- } else if (typeName.equals("int")) {
- field.setInt(obj, Integer.parseInt(value));
- } else if (typeName.equals("long")) {
- field.setLong(obj, Long.parseLong(value));
- } else if (typeName.equals("float")) {
- field.setFloat(obj, Float.parseFloat(value));
- } else if (typeName.equals("double")) {
- field.setDouble(obj, Double.parseDouble(value));
- }
- } else if (typeName.equals("java.lang.String")) { // 是否为String
- if (!value.equals("null")) {
- field.set(obj, value);
- }
- } else if (typeName.equals("[B")) { // 是否为byte[]
- if (!value.equals("null")) {
- // 用Base64将字符串转成byte[](SDK 2.2之后自带)
- field.set(obj, Base64.decode(value, Base64.DEFAULT));
- }
- } // 其他类型暂不需要
- }
- }
四、后记
Json与Object互相转化,可看《
Android实时绘制效果》附件工程内的JsonUtil。