Android XML小工具
<b>一、概述</b>
XML與Object互相轉化,支援8種基本類型、String和byte[]。byte[]需要經由base64編碼(API8以後才有,之前版本可以自己拷入)。
更多代碼及測試用例,見附件工程!
<b>二、Object –> XML</b>
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序列化
private void writeXml(XmlSerializer serializer, Object obj)
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);
}
<b>三、XML -> Object</b>
public class XmlParser {
* 分析XML将對應值賦予對象
* @param ins 輸入流
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分析器
private void parseXml(XmlPullParser parser, Object obj)
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) {
if (tagName.equals(field.getName())) {
return field;
return null;
* 給字段設值
* @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[]
// 用Base64将字元串轉成byte[](SDK 2.2之後自帶)
field.set(obj, Base64.decode(value, Base64.DEFAULT));
} // 其他類型暫不需要
<b>四、後記</b>
<a href="http://down.51cto.com/data/2360816" target="_blank">附件:http://down.51cto.com/data/2360816</a>
本文轉自winorlose2000 51CTO部落格,原文連結:http://blog.51cto.com/vaero/900852,如需轉載請自行聯系原作者