• Android--序列化XML数据


    前言

      之前有讲过在Android下如何解析XML文件的内容,这篇博客讲讲如何把一个对象序列化为XML格式,有时候一些项目中需要传递一些XML格式的数据。而对于如何解析XML,不了解的朋友可以看看其他三篇博客:SAX解析XMLPULL解析XMLDOM解析XML

    什么是XML?

      首先我们先了解一下什么是XML。XML,可扩展标记语言 (Extensible Markup Language) ,用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言,这是百度百科的解释。而XML是一种在Internet中传输数据的常见格式,它与HTML一样,都是SGML(标准通用标记语言),无论你是需要通过Internet访问数据,或者发送数据给Web服务,都可能需要用到XML的知识。恰恰Android应用程序需要和网络交互,否则只是一款单机的无互动的应用程序,所以很可能在Android应用程序开发的过程中使用到XML。

      由于XML的扩展性强,致使它需要有稳定的基础规则来支持扩展,该语法规则需要注意的是:

    1. 开始和结束标签匹配。
    2. 嵌套标签不能相互嵌套。
    3. 区分大小写。

    XML序列化

      当获取到一段数据后,如果需要把它序列化成XML的格式,通常有两种办法:

    1. 拼接字符串的形式序列化一个XML数据。
    2. 使用XmlSerializer类序列化一个XML数据。

      使用拼接字符串的方式很简单,就是个体力活,把需要序列化的对象,依照一定的格式序列化即可。下面通过一个示例讲解来演示如何拼接字符串,在示例中模拟联系人数据,然后对其进行序列化成XML,最后保存在SD卡上。

     1     private void backupToContact1(){
     2         StringBuilder sbuilder=new StringBuilder();
     3         // 设置XML的数据头
     4         sbuilder.append("<?xml version="1.0" encoding="utf-8"?>");
     5         sbuilder.append("<contacts>");
     6         // 遍历联系人信息
     7         for(Contact contact:Contacts){
     8             if(contact!=null){
     9                 sbuilder.append("<contact id='"+contact.getId()+"'>");
    10                 sbuilder.append("<name>");
    11                 sbuilder.append(contact.getName());
    12                 sbuilder.append("</name>");
    13                 
    14                 sbuilder.append("<number>");
    15                 sbuilder.append(contact.getNumber());
    16                 sbuilder.append("</number>");
    17                 
    18                 sbuilder.append("<address>");
    19                 sbuilder.append(contact.getAddress());
    20                 sbuilder.append("</address>");
    21                 
    22                 sbuilder.append("</contact>");
    23             }
    24         }            
    25         sbuilder.append("</contacts>");
    26         try {
    27             // 在SD卡上创建一个xml文件
    28             File file=new File(Environment.getExternalStorageDirectory(),"backup1.xml");
    29             FileOutputStream fos=new FileOutputStream(file);
    30             // 把序列化的数据写入到XML文件中
    31             fos.write(sbuilder.toString().getBytes());
    32             fos.close();
    33             Toast.makeText(MainActivity.this, "备份成功", 0).show();
    34         } catch (IOException e) {
    35             Toast.makeText(MainActivity.this, "备份失败", 0).show();
    36             e.printStackTrace();
    37         }
    38     }

      执行完之后,可以把SD卡上的XML文件导出到电脑上,查看其内容。

      对于拼接字符串而言,可以看出,很容易出错,尤其是每个标签内如果还存在属性值就更需要细心了。而且如果其内容存在特殊的符号,如“<、>”等,就会导致XML序列化后的XML文件出错,而使用XmlSerializer来序列化XML文件就不存在这些问题。

      下面介绍第二种方式,通过XmlSerializer类来序列化XML。那先了解一下XmlSerializer,XmlSerializer主要是是以数据流的形式序列化XML,而它是一个接口类型,无法直接实例化,需要通过一个静态方法Xml.newSerializer()获取对象。

      以下是一些常用方法:

    • setOutput(OutputStream,String):设置输出流,以及编码格式。
    • startDocument(String,boolean):第一个参数设置文档的编码格式,第二个参数设置是否是一个独立的文档,一般设置为true。
    • endDocument():标记XML文档的结束,XML文档标签均为成对出现,有始有终。
    • startTag(String,String):一个XML标签的开始,第一个参数为命名空间,一般为null即可,第二个参数为标签名。
    • endTag(String,String):一个XML标签的结束,第一个参数为命名空间,一般为null即可,第二个参数为标签名,有始有终。
    • attribute(String,String,String):设置一个标签的属性,第一个参数为命名空间,第二个参数是属性名,第三个参数为属性值。

      上面已经介绍过了XmlSerializer的常用方法,下面通过一个示例来演示XmlSerializer的使用。在示例中实现的功能和上面拼接字符串序列化XML一致,都是序列化模拟的联系人信息,然后以XML的格式保存在SD卡上。  

     1     private void backupToContact2(){
     2         try {
     3             // 在SD卡上创建一个文件
     4             File file=new File(Environment.getExternalStorageDirectory(),"backup2.xml");
     5             FileOutputStream fos=new FileOutputStream(file);
     6             // 获取一个XmlSerializer
     7             XmlSerializer serializer = Xml.newSerializer();
     8             // 设置XML的输出流以及编码格式
     9             serializer.setOutput(fos,"utf-8");
    10             // 设置文档的开头,以及编码格式
    11             serializer.startDocument("utf-8", true);
    12             
    13             // 开始标签
    14             serializer.startTag(null, "contacts");
    15             for(Contact contact:Contacts){
    16                 serializer.startTag(null, "contact");
    17                 // 设置contact标签的id属性
    18                 serializer.attribute(null, "id", contact.getId()+"");
    19                 serializer.startTag(null, "name");
    20                 serializer.text(contact.getName());
    21                 serializer.endTag(null, "name");
    22                 
    23                 serializer.startTag(null, "number");
    24                 serializer.text(contact.getNumber());
    25                 serializer.endTag(null, "number");
    26                 
    27                 serializer.startTag(null, "address");
    28                 serializer.text(contact.getAddress());
    29                 serializer.endTag(null, "address");
    30                 serializer.endTag(null, "contact");
    31             }
    32             // 一个结束标签
    33             serializer.endTag(null, "contacts");
    34             // 标记文档的结束
    35             serializer.endDocument();
    36             // 关闭输出流
    37             fos.close();
    38             Toast.makeText(MainActivity.this, "备份成功", 0).show();
    39         } catch (Exception e) {
    40             e.printStackTrace();
    41             Toast.makeText(MainActivity.this, "备份失败", 0).show();
    42         }        
    43     }

      保存成功之后,可以通过File Explorer导出XML文件查看其内容,上面两个示例序列化的XML文件一致,如下:

     1 <?xml version="1.0" encoding="utf-8"?>
     2 <contacts>
     3 <contact id="0">
     4 <name>Damon0</name>
     5 <number>18600000000</number>
     6 <address>beijing0</address>
     7 </contact>
     8 <contact id="1">
     9 <name>Damon1</name>
    10 <number>18600000001</number>
    11 <address>beijing1</address>
    12 </contact>
    13 <contact id="2">
    14 <name>Damon2</name>
    15 <number>18600000002</number>
    16 <address>beijing2</address>
    17 </contact>
    18 <contact id="3">
    19 <name>Damon3</name>
    20 <number>18600000003</number>
    21 <address>beijing3</address>
    22 </contact>
    23 <contact id="4">
    24 <name>Damon4</name>
    25 <number>18600000004</number>
    26 <address>beijing4</address>
    27 </contact>
    28 <contact id="5">
    29 <name>Damon5</name>
    30 <number>18600000005</number>
    31 <address>beijing5</address>
    32 </contact>
    33 <contact id="6">
    34 <name>Damon6</name>
    35 <number>18600000006</number>
    36 <address>beijing6</address>
    37 </contact>
    38 <contact id="7">
    39 <name>Damon7</name>
    40 <number>18600000007</number>
    41 <address>beijing7</address>
    42 </contact>
    43 <contact id="8">
    44 <name>Damon8</name>
    45 <number>18600000008</number>
    46 <address>beijing8</address>
    47 </contact>
    48 <contact id="9">
    49 <name>Damon9</name>
    50 <number>18600000009</number>
    51 <address>beijing9</address>
    52 </contact>
    53 </contacts>

       在示例中,访问了SD卡,所以需要在清单文件中加入SD卡写入权限:

    1     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

      源码下载

    总结

      因为拼接字符串的方式比较不直观,容易出错,量大了需要很细心才行,基本上是个体力活,而且如果内容存在对于一些对于XML格式数据有特殊意义的符号,会导致拼接后的XML数据无法正常被解析。一般情况下,推荐使用XmlSerializer来序列化XML数据,使用XmlSerializer来序列化XML不存在这方面的问题,对于一些特殊符号,它会自动对其进行转义。

     

  • 相关阅读:
    AngularJS概念概述和第一个使用例子
    什么是AngularJS
    AngularJS系列-翻译官网
    Unity3d 鼠标滚轮缩放效果
    Unity3d 正方体添加材质
    NGUI 由Empty创建Button
    NGUI Anchor三种type的不同
    【cocos2d-x 手游研发小技巧(5)获取网络图片缓存并展示】
    【cocos2d-x 手游研发小技巧(4)与Android混编实现换“头像图片”】
    【cocos2d-x 手游研发----博彩大转盘】
  • 原文地址:https://www.cnblogs.com/plokmju/p/android_XmlSerializer.html
Copyright © 2020-2023  润新知