【攻克Android (36):XML解析之一】DOM方式解析XML

本文围绕以下三个部分展开:

一、XML概述
二、DOM解析

案例一






一、XML概述

        (1)XML(eXtensible Markup Language):可扩展标记语言,属于一种标记语言。

        (2)XML是一种解析文件内容的语言,XML需要拥有“解析程序”(Parser)才可以处理XML的数据,XML重视对文件中的数据解析。

        XML解析器是指可以解析XML文件的程序。

        (3)XML与HTML

        HTML的目的是显示数据,重视的是数据显示的效果。

        XML在写法上十分类似HTML,在功能上能够补足HTML标记的不足,拥有更多的扩展性。

        XML并没有如同HTML—般的默认标记,事实上用户需要自己定义描述数据所需的各种标记。

        XML设计的目的是用来描述数据,着重在数据的自身上。


二、DOM解析

        DOM:Document Object Model,文本对象模型。

        DOM解析XML文件时,会将XML文件的所有内容以文档树方式存放在内存中,然后允许使用DOM API遍历XML树、检索所需的数据。

        使用DOM操作XML的代码看起来是比较直观的,并且在编码方面比基于SAX的实现更加简单。

        但是,因为DOM需要将XML文件的所有内容以文档树方式存放在内存中,所以内存的消耗比较大,特别对于运行Android的移动设备来说,因为设备的资源比较宝贵,所以建议还是采用SAX来解析XML文件,当然,如果XML文件的内容比较小采用DOM也是可行的。


案例一

【攻克Android (36):XML解析之一】DOM方式解析XML_第1张图片


        1. 在java下面创建 persons.xml。里面写入XML内容。

<?xml version="1.0" encoding="UTF-8"?>
<persons>    
	<person id="10">
		<name>段誉</name>
		<age>16</age>
	</person>
	
	<person id="11">
		<name>乔峰</name>
		<age>32</age>
	</person>
</persons>


<!--
  1.
  Table:
    persons : 根元素
    person子节点:一条记录
    属性id:主键列
    name/age:其他字段
    name/age的文本节点:其他字段的值


  Element Node 元素节点
  Text Node 文本节点
  
  xm.substring(start,length)
  new String(ch,start,length)
-->



        2. 创建 com.android.pojo 包,里面创建 Person.java 的 pojo 类,用来封装XML文件中的一条记录。

package com.android.pojo;

/**
 * Created by Xiangdong Lee on 2015/8/25.
 */
public class Person {
    private String id;
    private String name;
    private String age;

    @Override
    public String toString() {
        return "Person{" + "id=" +id +",name='" +name + '\'' +",age="+age+'?';
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }
}



        3. 创建com.android.service包,用于放处理业务逻辑的类。在该包下创建 DomPersonService.java 的类,是一个使用DOM方式解析XML的业务逻辑类。

package com.android.service;

import com.android.pojo.Person;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

/**
 * 通过 DOM 解析 XML文件  --  DOM 解析 Person 的 业务逻辑类
 *
 * Created by Xiangdong Lee on 2015/8/25.
 */
public class DomPersonService {
    public static List<Person> getPersons(InputStream is) throws Exception {
        List<Person> persons = new ArrayList<Person>();

        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
        // 在内存中形成dom树(缺点:耗内存) - 适合文件比较小
        Document document = builder.parse(is);

        Element root = document.getDocumentElement();
        NodeList personNodes = root.getElementsByTagName("person");
        for (int i = 0; i < personNodes.getLength(); i++) {
            Person person = new Person();
            Element personElement = (Element) personNodes.item(i);

            String id = personElement.getAttribute("id");

            String name = document.getElementsByTagName("name").item(i)
                    .getFirstChild().getNodeValue();
            String age = document.getElementsByTagName("age").item(i).getFirstChild()
                    .getNodeValue();

            // 把值封装到对象中
            person.setId(id);
            person.setName(name);
            person.setAge(age);

            // 把对象加入集合中
            persons.add(person);
        }
        return persons;
    }
}



        4. 在测试包下面创建一个单元测试类:PersonServiceTest,用于进行JUnit单元测试。

package com.android.dataparsing;

import android.test.InstrumentationTestCase;
import android.util.Log;

/**
 * Junit 单元测试 -- 要先连接真机/模拟器。
 *      第一步.继承 InstrumentationTestCase 测试案例类
 *      第二步.定义测试方法:方法名必须以 小写的 testXxx 开头
 *      第三步.选中方法名,右击 -> Run -> testXxx()
 *
 * Created by Xiangdong on 2015/8/25.
 */
public class PersonServiceTest extends InstrumentationTestCase {
    private static final String TAG = "MainActivity";

    public void testLog() {
        Log.v(TAG, "This is Junit.");
    }
}


【攻克Android (36):XML解析之一】DOM方式解析XML_第2张图片





        5. 在测试类中对DOM解析进行测试。写testDom测试方法。

package com.android.dataparsing;

import android.test.InstrumentationTestCase;
import android.util.Log;

import com.android.pojo.Person;
import com.android.service.DomPersonService;

import java.io.InputStream;
import java.util.List;

/**
 * Junit 单元测试 -- 要先连接真机/模拟器。
 * 第一步.继承 InstrumentationTestCase 测试案例类
 * 第二步.定义测试方法:方法名必须以 小写的 testXxx 开头
 * 第三步.选中方法名,右击 -> Run -> testXxx()
 * <p/>
 * Created by Xiangdong on 2015/8/25.
 */
public class PersonServiceTest extends InstrumentationTestCase {
    private static final String TAG = "MainActivity";

    public void testLog() {
        Log.v(TAG, "This is Junit.");
    }

    /**
     * 该方法有可能抛出异常,直接在此抛出即可
     *
     * @throws Exception
     */
    public void testDom() throws Exception {
        // xml文件读到流中间去了
        InputStream is = getClass().getClassLoader().getResourceAsStream("persons.xml");
        // 进行 DOM 解析 -- 因为 getPersons 是 static 的,因此直接用 类名.方法名
        List<Person> persons = DomPersonService.getPersons(is);
        // 用日志循环输出出来
        for (Person person : persons) {
            Log.v(TAG, person.toString());
        }
    }
}


        运行的时候,会报错:

【攻克Android (36):XML解析之一】DOM方式解析XML_第3张图片


        因为不能直接读取到java文件夹下面的persons.xml文件,而是通过DomPersonService类中,从流里面读取的。流中的文件是从真机/虚拟机中获取的。

        而persons.xml文件并不在真机/虚拟机中,因此要打包,将其放到其中。


        6. 使用流读取 classpath 下的文件(通过手工命令方式):

【攻克Android (36):XML解析之一】DOM方式解析XML_第4张图片


【攻克Android (36):XML解析之一】DOM方式解析XML_第5张图片


【攻克Android (36):XML解析之一】DOM方式解析XML_第6张图片


【攻克Android (36):XML解析之一】DOM方式解析XML_第7张图片



        然后,再测试,就可以正常解析了。

你可能感兴趣的:(android,xml,dom解析,Junit单元测试)