植物百科
一、案例描述
1、考核知识点
XML解析
2、练习目标
掌握XML的解析
3、需求分析
实际生活中,大多数人会在手机中安装一个天气预报的软件,如墨迹天气、懒人天气等。这些软件在获取天气信息时,都是通过解析XML文件得到的,下面就通过一个案例“植物百科”来演示如何解析XML文件。
4、设计思路(实现原理)
1) 创建plant.xml文件
2) 使用pull解析plant.xml并得到相应的植物信息
3) 在布局中更换植物的简介、图片
二、案例实现
(1)创建“植物百科”程序
创建“植物百科”程序,该程序的界面对应的布局文件activity_main.xml的代码如下所示:
<RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:id="@+id/imgv_plant"
android:layout_width="match_parent"
android:layout_height="150dp"
android:scaleType="matrix"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="内容简介"
android:layout_margin="10dp"
android:textColor="@android:color/darker_gray"/>
<TextView
android:id="@+id/tv_plants_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="5dp"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_alignParentBottom="true">
<Button
android:id="@+id/btn_xrq"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="仙人球"
android:background="@drawable/normal_button"/>
<Button
android:id="@+id/btn_xyc"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="薰衣草"
android:background="@drawable/normal_button"/>
<Button
android:id="@+id/btn_xrk"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="向日葵"
android:background="@drawable/normal_button"/>
</LinearLayout>
</RelativeLayout>
(2)创建plant.xml
在工程src根目录中创建一个plant.xml文件,该文件中包含三种植物的信息,具体如下所示:
<?xml version="1.0"encoding="UTF-8"?>
<plants>
<plantsInfo>
<name>仙人球</name>
<content>仙人球为多年生肉质多浆草本植物,是双子叶植物,在植物分类学中属于仙人掌科。茎呈球形或椭圆形,高可达25厘米,绿色,球体有纵棱若干条,棱上密生针刺,黄绿色,长短不一,作辐射状。花着生于纵棱刺丛中,银白色或粉红色,长喇叭形,长可达20厘米,喇叭外鳞片,鳞腑有长毛。仙人球开花一般在清晨或傍晚,持续时间几小时到一天。球体常侧生出许多小球,形态优美、高雅。</content>
</plantsInfo>
<plantsInfo>
<name>薰衣草</name>
<content>薰衣草原野生于法国和意大利南部地中海沿海的阿尔卑斯山南麓一带,以及西班牙、北非等地。13世纪,它是欧洲医学修道院园圃中的主要栽种植物。15世纪,海尔幅夏地区开始种植。16世纪末,在法国南部地区开始栽培。18世纪,萨里的密契、伦敦南区的熏衣山、法国的普罗旺斯、格拉斯附近的山区都以种植薰衣草而闻名,并成为世界闻名的旅游胜地。19世纪,英、澳等国相继引种栽培,现已遍及地中海与黑海沿岸诸国。</content>
</plantsInfo>
<plantsInfo>
<name>向日葵</name>
<content>向日葵又名朝阳花,因其花常朝着太阳而得名。英语称之为sunflower却不是因为它的这一特性,因为其黄花开似太阳的缘故。16世纪~17世纪sunflower一词从拉丁语flos solis借译过来。向日葵的法语,意大利语和西班牙语名称tournesol,girasol和girasol同汉语名称一样,也是基于“向日”这一特性来命名的。</content>
</plantsInfo>
</plants>
(3)创建javebeanPlantInfo类
从plant.xml代码中可以看出,每种植物信息都包含name、content属性,为了方便后续的使用,可以将这两个属性封装成一个Javabean,具体代码如下所示:
1 /**植物信息*/
2 public class PlantInfo {
3 private String plantName;
4 private String plantContent;
5 public String getPlantName() {
6 return plantName;
7 }
8 public void setPlantName(String plantName) {
9 this.plantName = plantName;
10 }
11 public String getPlantContent() {
12 return plantContent;
13 }
14 public void setPlantContent(String plantContent) {
15 this.plantContent = plantContent;
16 }
17 }
(4)创建工具类utils
为了代码的更加易于阅读,避免大量代码都在一个类中,因此创建一个用来解析XML文件的工具类utils。utils类中定义了一个getPlantsInfos()方法,该方法中包含了解析XML文件的逻辑代码,具体代码如下所示:
1 /** 解析xml文件的工具类 */
2 public class utils {
3 // 返回天气信息的集合
4 public static List<PlantInfo> getPlantInfos(InputStream is)
5 throws Exception {
6 // 得到pull解析器
7 XmlPullParser parser = Xml.newPullParser();
8 // 初始化解析器,第一个参数代表包含xml的数据
9 parser.setInput(is, "utf-8");
10 List<PlantInfo> plantInfos = null;
11 PlantInfo plantInfo = null;
12 // 得到当前事件的类型
13 int type = parser.getEventType();
14 // END_DOCUMENT文档结束标签
15 while (type != XmlPullParser.END_DOCUMENT) {
16 switch (type) {
17 // 一个节点的开始标签
18 case XmlPullParser.START_TAG:
19 // 解析到全局开始的标签 infos 根节点
20 if ("plants".equals(parser.getName())) {
21 plantInfos = new ArrayList<PlantInfo>();
22 } else if("plantsInfo".equals(parser.getName())) {
23 plantInfo = new PlantInfo();
24 } else if ("name".equals(parser.getName())){
25 // parset.nextText()得到该tag节点中的内容
26 String name = parser.nextText();
27 plantInfo.setPlantName(name);
28 } else if("content".equals(parser.getName())) {
29 String content = parser.nextText();
30 plantInfo.setPlantContent(content);
31 }
32 break;
33 // 一个节点结束的标签
34 case XmlPullParser.END_TAG:
35 // 一个城市的信息处理完毕,city的结束标签
36 if ("plantsInfo".equals(parser.getName())){
37 // 一个城市的信息 已经处理完毕了.
38 plantInfos.add(plantInfo);
39 plantInfo = null;
40 }
41 break;
42 }
43 // 只要不解析到文档末尾,就解析下一个条目。得到下一个节点的事件类型
44 // 注意,这个一定不能忘,否则会成为死循环
45 type = parser.next();
46 }
47 return plantInfos;
48 }
49 }
(5)编写与界面交互的逻辑代码
在MainActivity中编写与界面交互的逻辑代码,具体如下所示:
1 public class MainActivityextends Activity implements OnClickListener {
2 private List<PlantInfo> plantInfos;
3 private TextView mPlantContentTV;
4 private ImageView mPlantImgv;
5 @Override
6 protected void onCreate(Bundle savedInstanceState) {
7 super.onCreate(savedInstanceState);
8 setContentView(R.layout.activity_main);
9 try {
10 //获取植物信息
11 plantInfos = utils.getPlantInfos(MainActivity.class
12 .getClassLoader().getResourceAsStream("plant.xml"));
13
14 } catch (Exception e) {
15 e.printStackTrace();
16 }
17 initView();
18 }
19 /**
20 * 初始化控件
21 */
22 private void initView() {
23 findViewById(R.id.btn_xrq).setOnClickListener(this);
24 findViewById(R.id.btn_xrk).setOnClickListener(this);
25 findViewById(R.id.btn_xyc).setOnClickListener(this);
26 mPlantContentTV =(TextView)findViewById(R.id.tv_plants_content);
27 mPlantImgv =(ImageView) findViewById(R.id.imgv_plant);
28 mPlantContentTV.setText("\u3000\u3000"+plantInfos.get(0).getPlantContent());
29 mPlantImgv.setBackgroundResource(R.drawable.a);
30 }
31 @Override
32 public void onClick(View v) {
33 switch (v.getId()) {
34 case R.id.btn_xrq:
35 //设置植物简介
36 mPlantContentTV.setText("\u3000\u3000"+plantInfos.get(0).getPlantContent());
37 mPlantImgv.setBackgroundResource(R.drawable.a);
38 break;
39 case R.id.btn_xyc:
40 mPlantContentTV.setText("\u3000\u3000"+plantInfos.get(1).getPlantContent());
41 mPlantImgv.setBackgroundResource(R.drawable.c);
42 break;
43 case R.id.btn_xrk:
44 mPlantContentTV.setText("\u3000\u3000"+plantInfos.get(2).getPlantContent());
45 mPlantImgv.setBackgroundResource(R.drawable.b);
46 break;
47 }
48 }
49 }
三、案例总结
1、在使用pull解析时,只要不解析到文档末尾,就需要解析下一个条目。得到下一个节点的事件类型可使用代码type = parser.next();
2、往TextView的setText()方法传入“\u3000”代表空格。

