Android XML小工具
 
一、概述
    XML与Object互相转化,支持8种基本类型、String和byte[]。byte[]需要经由base64编码(API8以后才有,之前版本可以自己拷入)。
    更多代码及测试用例,见附件工程!
 
二、Object –> XML
 
 
  
  1. public class XmlBuilder {  
  2.  
  3.     /**  
  4.      * 由对象属性生成XML  
  5.      *   
  6.      * @param outs 输出流  
  7.      * @param encoding 字符编码  
  8.      * @param obj 对象  
  9.      */ 
  10.     public void buildXml(OutputStream outs, String encoding, Object obj)  
  11.             throws IllegalArgumentException, IllegalStateException,  
  12.             IOException, IllegalAccessException {  
  13.         XmlSerializer serializer = Xml.newSerializer(); // 创建一个Xml序列化  
  14.         serializer.setOutput(outs, encoding); // 设置输出流及字符编码  
  15.         serializer.startDocument(encoding, true); // 开始文档  
  16.         writeXml(serializer, obj); // 写文档  
  17.         serializer.endDocument(); // 结束文档  
  18.         outs.close(); // 关闭输出流  
  19.     }  
  20.  
  21.     /**  
  22.      * 将对象属性写入XML  
  23.      *   
  24.      * @param serializer XML序列化  
  25.      * @param obj 对象  
  26.      */ 
  27.     private void writeXml(XmlSerializer serializer, Object obj)  
  28.             throws IllegalArgumentException, IllegalStateException,  
  29.             IOException, IllegalAccessException {  
  30.  
  31.         final String tag_type = "type";  
  32.         final String tag_value = "value";  
  33.  
  34.         Class<?> cls = obj.getClass(); // 获取对象运行时类  
  35.         String clsName = cls.getName(); // 获取对象名称  
  36.  
  37.         serializer.startTag(null, clsName);  
  38.  
  39.         Field[] fields = cls.getDeclaredFields(); // 返回类声明的所有字段  
  40.  
  41.         boolean isWrite;  
  42.         Class<?> type; // 变量类型  
  43.         String varName, typeName, value = null// 变量名、类型名、变量值  
  44.         for (Field field : fields) {  
  45.             isWrite = true;  
  46.             type = field.getType(); // 获取变量类型  
  47.             typeName = type.getName(); // 获取类型名  
  48.             field.setAccessible(true); // 设置变量可访问  
  49.             if (type.isPrimitive()) { // 是否为基本类型  
  50.                 if (typeName.equals("boolean")) {  
  51.                     value = String.valueOf(field.getBoolean(obj));  
  52.                 } else if (typeName.equals("char")) {  
  53.                     // char型未赋值,为默认'\u0000'时,会影响parser.next()  
  54.                     char c = field.getChar(obj);  
  55.                     value = c == '\u0000' ? "null" : String.valueOf(field  
  56.                             .getChar(obj));  
  57.                 } else if (typeName.equals("byte")) {  
  58.                     value = String.valueOf(field.getByte(obj));  
  59.                 } else if (typeName.equals("short")) {  
  60.                     value = String.valueOf(field.getShort(obj));  
  61.                 } else if (typeName.equals("int")) {  
  62.                     value = String.valueOf(field.getInt(obj));  
  63.                 } else if (typeName.equals("long")) {  
  64.                     value = String.valueOf(field.getLong(obj));  
  65.                 } else if (typeName.equals("float")) {  
  66.                     value = String.valueOf(field.getFloat(obj));  
  67.                 } else if (typeName.equals("double")) {  
  68.                     value = String.valueOf(field.getDouble(obj));  
  69.                 }  
  70.             } else if (typeName.equals("java.lang.String")) { // 是否为String  
  71.                 value = field.get(obj) == null ? "null" : field.get(obj)  
  72.                         .toString();  
  73.             } else if (typeName.equals("[B")) { // 是否为byte[]  
  74.                 typeName = getTypeHelper(type); // 字符代码->[]形式  
  75.                 // 用Base64将byte[]转成字符串(SDK 2.2之后自带)  
  76.                 value = field.get(obj) == null ? "null" 
  77.                         : Base64.encodeToString((byte[]) field.get(obj),  
  78.                                 Base64.DEFAULT);  
  79.             } else { // 其他类型暂不需要  
  80.                 isWrite = false;  
  81.             }  
  82.             if (isWrite) {  
  83.                 varName = field.getName(); // 获取变量名  
  84.                 serializer.startTag(null, varName);  
  85.                 writeTag(serializer, tag_type, typeName);  
  86.                 writeTag(serializer, tag_value, value);  
  87.                 serializer.endTag(null, varName);  
  88.             }  
  89.         }  
  90.  
  91.         serializer.endTag(null, clsName);  
  92.     }  
  93.  
  94.     /**  
  95.      * 字符代码->[]形式  
  96.      */ 
  97.     private String getTypeHelper(Class<?> type) {  
  98.         if (type.isArray()) {  
  99.             Class<?> c = type.getComponentType();  
  100.             return getTypeHelper(c) + "[]";  
  101.         } else {  
  102.             return type.getName();  
  103.         }  
  104.     }  
  105.  
  106.     /**  
  107.      * 写一个标签及值  
  108.      */ 
  109.     private void writeTag(XmlSerializer serializer, String tag, String value)  
  110.             throws IllegalArgumentException, IllegalStateException, IOException {  
  111.         serializer.startTag(null, tag);  
  112.         serializer.text(value);  
  113.         serializer.endTag(null, tag);  
  114.     }  
  115.  
 
三、XML -> Object
 
 
  
  1. public class XmlParser {  
  2.  
  3.     /**  
  4.      * 分析XML将对应值赋予对象  
  5.      *   
  6.      * @param ins 输入流  
  7.      * @param encoding 字符编码  
  8.      * @param obj 对象  
  9.      */ 
  10.     public void parseXml(InputStream ins, String encoding, Object obj)  
  11.             throws XmlPullParserException, IllegalArgumentException,  
  12.             UnsupportedEncodingException, IllegalAccessException, IOException {  
  13.         XmlPullParser parser = Xml.newPullParser(); // 创建一个Xml分析器  
  14.         parser.setInput(ins, encoding); // 设置输入流及字符编码  
  15.         parseXml(parser, obj); // 解析文档  
  16.         ins.close(); // 关闭输入流  
  17.     }  
  18.  
  19.     /**  
  20.      * 分析XML详细步骤  
  21.      *   
  22.      * @param parser Xml分析器  
  23.      * @param obj 对象  
  24.      */ 
  25.     private void parseXml(XmlPullParser parser, Object obj)  
  26.             throws XmlPullParserException, IllegalArgumentException,  
  27.             UnsupportedEncodingException, IllegalAccessException, IOException {  
  28.  
  29.         final String tag_value = "value";  
  30.  
  31.         Class<?> cls = obj.getClass(); // 获取对象运行时类  
  32.         String clsName = cls.getName(); // 获取对象名称  
  33.  
  34.         Field[] fields = cls.getDeclaredFields(); // 返回类声明的所有字段  
  35.  
  36.         Field field = null;  
  37.  
  38.         int tagDepth; // 标签深度  
  39.         String tagName; // 标签名称  
  40.         int eventType = parser.getEventType(); // 获取事件类型  
  41.         while (true) {  
  42.             if (eventType == XmlPullParser.START_DOCUMENT) {  
  43.                 // Log.i("START_DOCUMENT", "=START_DOCUMENT");  
  44.             } else if (eventType == XmlPullParser.START_TAG) {  
  45.                 // Log.i("START_TAG", "=START_TAG");  
  46.  
  47.                 tagDepth = parser.getDepth(); // 获取标签深度  
  48.                 tagName = parser.getName(); // 获取标签名称  
  49.  
  50.                 if (tagDepth == 1) { // 一级标签  
  51.                     if (!tagName.equals(clsName)) { // 与对象名称不一致时  
  52.                         throw new XmlPullParserException("XML首标签名与对象名称不一致");  
  53.                     }  
  54.                 } else if (tagDepth == 2) { // 二级标签  
  55.                     // 判断标签名称是否符合类的某一字段名称  
  56.                     field = hasField(tagName, fields);  
  57.                 } else if (tagDepth == 3 && field != null) { // 三级标签  
  58.                     if (tagName.equals(tag_value)) { // 如果是value标签  
  59.                         setValue(obj, field, parser.nextText());  
  60.                         field = null;  
  61.                     }  
  62.                 }  
  63.             } else if (eventType == XmlPullParser.END_TAG) {  
  64.                 // Log.i("END_TAG", "=END_TAG");  
  65.             } else if (eventType == XmlPullParser.TEXT) {  
  66.                 // Log.i("TEXT", "=TEXT");  
  67.             } else if (eventType == XmlPullParser.END_DOCUMENT) {  
  68.                 // Log.i("END_DOCUMENT", "=END_DOCUMENT");  
  69.                 break;  
  70.             }  
  71.             eventType = parser.next(); // 下一解析事件  
  72.         }  
  73.     }  
  74.  
  75.     /**  
  76.      * 判断标签名称是否符合类的某一字段名称  
  77.      *   
  78.      * @param tagName 标签名称  
  79.      * @param fields 类字段集合  
  80.      * @return 符合:Field;否则:null  
  81.      */ 
  82.     private Field hasField(String tagName, Field[] fields) {  
  83.         for (Field field : fields) {  
  84.             if (tagName.equals(field.getName())) {  
  85.                 return field;  
  86.             }  
  87.         }  
  88.         return null;  
  89.     }  
  90.  
  91.     /**  
  92.      * 给字段设值  
  93.      *   
  94.      * @param obj 对象  
  95.      * @param field 字段  
  96.      * @param value 值  
  97.      */ 
  98.     private void setValue(Object obj, Field field, String value)  
  99.             throws IllegalArgumentException, IllegalAccessException,  
  100.             UnsupportedEncodingException {  
  101.         Class<?> type = field.getType(); // 变量类型  
  102.         String typeName = type.getName(); // 类型名  
  103.         field.setAccessible(true); // 设置变量可访问  
  104.         if (type.isPrimitive()) { // 是否为基本类型  
  105.             if (typeName.equals("boolean")) {  
  106.                 field.setBoolean(obj, Boolean.parseBoolean(value));  
  107.             } else if (typeName.equals("char")) {  
  108.                 if (!value.equals("null")) {  
  109.                     field.setChar(obj, value.charAt(0));  
  110.                 }  
  111.             } else if (typeName.equals("byte")) {  
  112.                 field.setByte(obj, Byte.parseByte(value));  
  113.             } else if (typeName.equals("short")) {  
  114.                 field.setShort(obj, Short.parseShort(value));  
  115.             } else if (typeName.equals("int")) {  
  116.                 field.setInt(obj, Integer.parseInt(value));  
  117.             } else if (typeName.equals("long")) {  
  118.                 field.setLong(obj, Long.parseLong(value));  
  119.             } else if (typeName.equals("float")) {  
  120.                 field.setFloat(obj, Float.parseFloat(value));  
  121.             } else if (typeName.equals("double")) {  
  122.                 field.setDouble(obj, Double.parseDouble(value));  
  123.             }  
  124.         } else if (typeName.equals("java.lang.String")) { // 是否为String  
  125.             if (!value.equals("null")) {  
  126.                 field.set(obj, value);  
  127.             }  
  128.         } else if (typeName.equals("[B")) { // 是否为byte[]  
  129.             if (!value.equals("null")) {  
  130.                 // 用Base64将字符串转成byte[](SDK 2.2之后自带)  
  131.                 field.set(obj, Base64.decode(value, Base64.DEFAULT));  
  132.             }  
  133.         } // 其他类型暂不需要  
  134.     }  
  135.  
 
四、后记
    Json与Object互相转化,可看《 Android实时绘制效果》附件工程内的JsonUtil。