使用xml作为数据交互的载体是Android中非常重要的功能,比如天气预报数据、短信备份数据、通讯录数据都可以以xml的格式通过网络传输。
为了演示Xml数据的操作,我模拟了一个短信备份的案例。
需求:界面如图1-10所示。上面是三个Button,前两个分别对应两种不同方式生成xml,第三个Button点击后解析备份的xml文件,然后将数据展现在下面的ScrollView中。短信数据是模拟的假数据。
生成的xml格式如文件1-10。
【文件1-10】 xml文件格式
1. <?xml version="1.0" encoding="utf-8" standalone="yes" ?> 2. <smses> 3. <sms> 4. <address>5554</address> 5. <body>我是内容<>0</body> 6. <time>1445595309201</time> 7. </sms> 8. <sms> 9. <address>5555</address> 10. <body>我是内容<>1</body> 11. <time>1445595309201</time> 12. </sms> 13. ............. 14. </smses>
2.7.1 编写布局
【文件1-11】 activity_main.xml
15. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 16. xmlns:tools="http://schemas.android.com/tools" 17. android:layout_width="match_parent" 18. android:layout_height="match_parent" 19. android:orientation="vertical" > 20. 21. <Button 22. android:layout_width="match_parent" 23. android:layout_height="wrap_content" 24. android:onClick="click1" 25. android:text="生成xml1" /> 26. 27. <Button 28. android:layout_width="match_parent" 29. android:layout_height="wrap_content" 30. android:onClick="click2" 31. android:text="生成xml2" /> 32. 33. <Button 34. android:layout_width="match_parent" 35. android:layout_height="wrap_content" 36. android:onClick="click3" 37. android:text="解析xml" /> 38. 39. <ScrollView 40. android:layout_width="match_parent" 41. android:layout_height="wrap_content" > 42. 43. <TextView 44. android:id="@+id/tv_sms" 45. android:layout_width="match_parent" 46. android:layout_height="wrap_content" /> 47. </ScrollView> 48. 49. </LinearLayout>
技能:
在上面布局中首次使用了ScrollView控件,其特点如下:
1、只能有一个子节点,但是子节点可以再包含多个子节点,也就是只能有一个孩子,但可以有多个孙子。
2、当包含的子控件高度超过ScrollView的高度时可以垂直滚动子控件。
1.7.2 拼接字符串方式生成Xml文件【文件1-12】 MainActivity.java 代码片段
1. /* 2. * 第一种方式生成xml 3. */ 4. public void click1(View view) throws Exception { 5. StringBuilder sb = new StringBuilder(); 6. sb.append("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>"); 7. sb.append("<smses>"); 8. for (int i = 0; i < 50; i++) { 9. sb.append("<sms>"); 10. sb.append("<address>"); 11. sb.append(5554 + i); 12. sb.append("</address>"); 13. sb.append("<body>"); 14. sb.append("我是短信内容" + i); 15. sb.append("</body>"); 16. sb.append("<time>"); 17. sb.append(new Date().getTime()); 18. sb.append("</time>"); 19. sb.append("</sms>"); 20. } 21. sb.append("</smses>"); 22. /* 23. * 使用系统提供的方法 获取文件输出流 24. */ 25. FileOutputStream fos = this.openFileOutput("info.xml",MODE_PRIVATE); 26. fos.write(sb.toString().getBytes()); 27. fos.close(); 28. }
技能:
上面的代码虽然也可以生成xml文件,但是无法对特殊字符进行处理,比如如果短信内容包含“</>”符号,那么xml解析器就无法完成正确的解析。因此使用的前提是你确定数据内容没有特殊字符。
1.7.3 使用XmlSerializer生成Xml文件
【文件1-13】 MainActivity.java 代码片段
1. /* 2. * 第二种方式生成xml 3. * 使用Android提供的API 4. */ 5. public void click2(View view) throws Exception { 6. //在data目录中创建info2.xml文件,获取输出流 7. FileOutputStream fos = openFileOutput("info2.xml",MODE_PRIVATE); 8. //通过Xml类创建一个Xml序列化器 9. XmlSerializer serializer = Xml.newSerializer(); 10. //给序列化器设置输出流和输出流编码 11. serializer.setOutput(fos,"utf-8"); 12. /* 13. * 让序列化器开发写入xml的头信息,其本质是写入内容: 14. * "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>" 15. */ 16. serializer.startDocument("utf-8",true); 17. /* 18. * 开始写入smses标签, 19. * 第一个参数是该标签的命名空间, 这里不需要 20. */ 21. serializer.startTag(null,"smses"); 22. for (int i = 0; i < 50; i++) { 23. //开始sms标签 24. serializer.startTag(null,"sms"); 25. //开始address标签 26. serializer.startTag(null,"address"); 27. //在address标签中间写入文本 28. serializer.text("" + (5554 + i)); 29. //结束address标签 30. serializer.endTag(null,"address"); 31. //开始body标签 32. serializer.startTag(null,"body"); 33. //在body标签中间写入文本 34. serializer.text("我是内容<>" + i); 35. //结束body标签 36. serializer.endTag(null,"body"); 37. serializer.startTag(null,"time"); 38. serializer.text(new Date().getTime()+""); 39. serializer.endTag(null,"time"); 40. //结束sms标签 41. serializer.endTag(null,"sms"); 42. } 43. //结束smses标签 44. serializer.endTag(null,"smses"); 45. //结束文档 46. serializer.endDocument(); 47. fos.close(); 48. }
注意:
使用XmlSerializer生成xml文件是推荐的方式,因为该api内部已经实现了对特殊字符的处理。
1.7.4 使用Pull解析Xml格式数据asserts资源目录中的文件只能读不能写,多用于随apk一起发布的固定不变的数据,比如可以将国内所有的城市列表放在里面。
这里将1.7.3节中生成的info2.xml放到asserts目录中,然后读取、解析、展现。
【文件1-14】 MainActivity.java 代码片段
1. //使用pull解析xml数据 2. public void click3(View v)throws Exception{ 3. /* 4. * 将解析出来的数据封装在Sms中,然后保存到ArrayList中 5. * Sms是自定义的一个JavaBean 6. */ 7. ArrayList<Sms> smses = null; 8. Sms sms = null; 9. /* 10. * 调用父类提供的getAssets()方法获取AssertManager对象 11. */ 12. AssetManager assetManager = getAssets(); 13. //使用assetManager的open方法直接获取输入流对象 14. InputStream inputStream = assetManager.open("info2.xml"); 15. //通过Xml的静态方法获取Xml解析器 16. XmlPullParser parser = Xml.newPullParser(); 17. //设置输入流和编码 18. parser.setInput(inputStream,"utf-8"); 19. //获取事件类型 20. int event = parser.next(); 21. //如果没有解析到文档的结尾,则循环解析 22. while(event!=XmlPullParser.END_DOCUMENT){ 23. //获取当前解析到的标签名称 24. String tagName = parser.getName(); 25. //如果是“开始标签”事件 26. if (event==XmlPullParser.START_TAG) { 27. //判断当前解析到的开始标签是哪个 28. if ("smses".equals(tagName)) { 29. smses = new ArrayList<Sms>(); 30. }else if ("sms".equals(tagName)) { 31. sms = new Sms(); 32. }else if ("address".equals(tagName)) { 33. sms.setAddress(parser.nextText()); 34. }else if ("body".equals(tagName)) { 35. sms.setBody(parser.nextText()); 36. }else if ("time".equals(tagName)) { 37. sms.setTime(parser.nextText()); 38. } 39. //如果是“结束标签”事件 40. }else if (event == XmlPullParser.END_TAG) { 41. if ("sms".equals(tagName)) { 42. //如果是sms结尾,则将创建的sms对象添加到集合中 43. smses.add(sms); 44. } 45. } 46. //继续获取下一个事件 47. event = parser.next(); 48. } 49. inputStream.close(); 50. //将数据展示到界面 51. showSms(smses); 52. 53. } 54. /* 55. * 将短信显示到TextView中 56. */ 57. private void showSms(ArrayList<Sms> smses){ 58. StringBuilder sb = new StringBuilder(); 59. for(Sms s : smses){ 60. sb.append(s.toString()+"\n"); 61. } 62. tv_sms.setText(sb.toString()); 63. }注意: 在上面的代码中我们不仅学到如何解析xml,还学到了如何读取aserts目录中的数据。 1.7.5 Pull解析和SAX解析对比 Pull解析器的运行方式与SAX解析器相似,都属于事件驱动模式。它提供了类似的事件,如:开始元素和结束元素事件,使用parser.next()可以进入下一个元素并触发相应事件。事件将作为数值代码被发送,因此可以使用一个switch对感兴趣的事件进行处理。当元素开始解析时,调用parser.nextText()方法可以获取下一个Text类型元素的值。 SAX解析器的工作方式是自动将事件推入事件处理器进行处理,因此你不能控制事件的处理主动结束;而Pull解析器的工作方式为允许你的应用程序代码主动从解析器中获取事件,正因为是主动获取事件,因此可以在满足了需要的条件后不再获取事件,结束解析。 原文链接:https://www.f2er.com/xml/294979.html