后台(07)——XML和JUnit-阿里云开发者社区

开发者社区> 开发与运维> 正文
登录阅读全文

后台(07)——XML和JUnit

简介: 探索Android软键盘的疑难杂症 深入探讨Android异步精髓Handler 详解Android主流框架不可或缺的基石 站在源码的肩膀上全解Scroller工作机制 Android多分...

探索Android软键盘的疑难杂症
深入探讨Android异步精髓Handler
详解Android主流框架不可或缺的基石
站在源码的肩膀上全解Scroller工作机制


Android多分辨率适配框架(1)— 核心基础
Android多分辨率适配框架(2)— 原理剖析
Android多分辨率适配框架(3)— 使用指南


自定义View系列教程00–推翻自己和过往,重学自定义View
自定义View系列教程01–常用工具介绍
自定义View系列教程02–onMeasure源码详尽分析
自定义View系列教程03–onLayout源码详尽分析
自定义View系列教程04–Draw源码分析及其实践
自定义View系列教程05–示例分析
自定义View系列教程06–详解View的Touch事件处理
自定义View系列教程07–详解ViewGroup分发Touch事件
自定义View系列教程08–滑动冲突的产生及其处理


版权声明


本文简介

本文主要介绍XML及其常用的解析方式和JUnit单元测试


XML简介

eXtensible Markup Language简称XML,它是一门可扩展标记语言;之所以称其为可扩展语言,是因为XML的标签都是自定义的。与HTML用于数据展示不同,XML主要用于数据的存储,比如Web开发中的众多配置文件都是由XML实现的。除了作用不一样以外,XML较HMTL而言语法也更加严格。

现在,我们来看一个非常简单的XML文件

<?xml version="1.0" encoding="UTF-8"?>
<students>
   <student number="1">
     <name>空空苍井</name>
     <age>23</age>
     <address>东京</address>
   </student>

    <student number="2">
     <name>小泽玛丽</name>
     <age>22</age>
     <address>大阪</address>
   </student>

    <student number="3">
     <name>杉原杏璃</name>
     <age>19</age>
     <address>仙台</address>
   </student>

</students>

在该示例中定义了根标签<students></students>然后在里面放了三个<student></student>标签用于表示每一个学生的信息;其中每个学生又包括了name,age,address

请注意XML的书写规范:

  • 将<?xml version=”1.0” encoding=”UTF-8”?>置于XML文档第一行
  • XML文档中必须有且仅有有一个根元素
  • XML文档中的元素需要正确闭合
  • XML文档中的元素需要正确嵌套
  • XML文档中的元素名称区分大小写
  • XML文档中的属性值必须用引号引起来

XML的约束

我们可以通过XML的约束来限制XML内容的书写,就像在Java中为集合指定了泛型来约束存入集合中的数据一样;我们可在约束文档定义在XML中允许出现的元素名称、属性及元素出现的顺序等等。XML中常用的约束有DTD和Schema,现在分别介绍。

DTD

DTD(Document Type Definition)文档类型定义,请看如下示例:

<!ELEMENT students (student*) >
<!ELEMENT student (name,age,address)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT age (#PCDATA)>
<!ELEMENT address (#PCDATA)>
<!ATTLIST student number ID #REQUIRED>

在此定义一个.dtd文件,在该文件中约束了xml的元素和属性。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE students SYSTEM  "studentDTD.dtd">

<students>
   <student number="number1">
     <name>空空苍井</name>
     <age>23</age>
     <address>东京</address>
   </student>

    <student number="number2">
     <name>小泽玛丽</name>
     <age>22</age>
     <address>大阪</address>
   </student>

    <student number="number3">
     <name>杉原杏璃</name>
     <age>19</age>
     <address>仙台</address>
   </student>

</students>

我们在该XML文件中使用刚才定义的DTD文件,请参见第2行代码。此时,我们假如写了DTD中未声明的标签就会报错;类似地,其他未遵守DTD文件的写法也会报错。其实,利用DTD文件约束XML的方式还是有些呆板,可读性也不强。所以,请看下面的Schema约束。

Schema

Schema也是一种用于定义和描述XML文档结构与内容的模式语言,其出现是为了优化DTD的局限性。请看如下示例:

<?xml version="1.0"?>
<xsd:schema 
    xmlns="http://www.stay4it.com" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    targetNamespace="http://www.stay4it.com" 
    elementFormDefault="qualified">

    <xsd:element name="students" type="studentsType" />
    <xsd:complexType name="studentsType">
        <xsd:sequence>
            <xsd:element name="student" type="studentType" minOccurs="0" maxOccurs="unbounded" />
        </xsd:sequence>
    </xsd:complexType>
    <xsd:complexType name="studentType">
        <xsd:sequence>
            <xsd:element name="name" type="xsd:string" />
            <xsd:element name="age" type="ageType" />
            <xsd:element name="gender" type="genderType" />
        </xsd:sequence>
        <xsd:attribute name="number" type="numberType" use="required" />
    </xsd:complexType>
    <xsd:simpleType name="genderType">
        <xsd:restriction base="xsd:string">
            <xsd:enumeration value="male" />
            <xsd:enumeration value="female" />
        </xsd:restriction>
    </xsd:simpleType>
    <xsd:simpleType name="ageType">
        <xsd:restriction base="xsd:integer">
            <xsd:minInclusive value="0" />
            <xsd:maxInclusive value="130" />
        </xsd:restriction>
    </xsd:simpleType>
    <xsd:simpleType name="numberType">
        <xsd:restriction base="xsd:string">
            <xsd:pattern value="stay4it_\d{3}" />
        </xsd:restriction>
    </xsd:simpleType>
</xsd:schema> 

在此定义一个.xsd文件,在该文件中约束了xml的元素和属性。请注意,在该文件中的限制条件非常细致。比如:限制了元素的类型,取值范围,出现次数等。

<?xml version="1.0" encoding="UTF-8"?>

<students 
    xmlns="http://www.stay4it.com"
    xsi:schemaLocation="http://www.stay4it.com studentSchema.xsd"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <student number="stay4it_101">
     <name>空空苍井</name>
     <age>23</age>
     <gender>female</gender>
   </student>

    <student number="stay4it_102">
     <name>小泽玛丽</name>
     <age>22</age>
     <gender>female</gender>
   </student>

    <student number="stay4it_103">
     <name>杉原杏璃</name>
     <age>19</age>
     <gender>female</gender>
   </student>

</students>

在该XML文档中采用刚才定义的Schema约束XML的书写。同样地,如果所书写的XML代码违反了该Schema约束那么会报错。


XML文档的解析方式

常用的解析XML文档的方式有DOM解析和SAX解析。

  • DOM解析

    将XML文档加载进内存形成一颗DOM树(document对象)并将文档的各个组成部分封装为对象。所以,可以对DOM树进行增删改查。但是DOM树非常占内存,解析速度较慢,故DOM解析不适合较为复杂的XML文件。

    如果说Java是面向对象编程,那么DOM是面向节点编程
    1 、整个XML文档就是一个文档(Document)节点。
    2 、文档中每个元素是也是一个元素(Element)节点
    3 、元素中的文字则是文本(Text)节点。
    4 、元素的属性是属性(Attr)节点。
    5 、标签之间的空格换行也是节点!
    6 、总之,XML文档中的每个成分都是一个节点

    由此可见,XML文档中每一个组成部分都是节点。所以,元素一定是节点,而节点不一定是元素。

  • SAX解析
    相比于DOM,SAX是一种速度更快,更有效的方法。SAX基于事件驱动,它逐行读取文档,一边读取一边解析,所以该方式占内存非常小,速度很快。而且在解析过程的任意时刻均可停止解析,但是该方式只能读取XML不能回写。

在开发中常用DOM4J和XPATH解析XML文件,先对其分别介绍。

利用DOM4J解析XML

请看如下示例:

package cn.xml;

import java.util.List;

import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
import org.junit.Test;

/**
 * 本文作者:谷哥的小弟
 * 博客地址:http://blog.csdn.net/lfdfhl
 */
public class TestDOM4J {
    @Test
    public void testDOM4J01() throws DocumentException{
         SAXReader reader = new SAXReader();
         Document document = reader.read("src/student.xml");
         Element rootElement = document.getRootElement();

         List<Element> elementList = rootElement.elements();
         int elementSize=elementList.size();
         int nodeCount=rootElement.nodeCount();

         System.out.println("根节点一共有"+elementSize+"个子元素");
         System.out.println("根节点一共有"+nodeCount+"个子节点");
    }

    @Test 
    public void testDOM4J02() throws DocumentException{
        SAXReader reader = new SAXReader();
         Document document = reader.read("src/student.xml");
         Element rootElement = document.getRootElement();
         analyzeElement(rootElement);
    }

    private void analyzeElement(Element element) {
        int nodeCount=element.nodeCount();
        for (int i = 0; i < nodeCount; i++) {
            Node node = element.node(i);
            if(node instanceof Element){
                Element elem=(Element) node;
                String elementName=elem.getName();
                List<Attribute> attrivuteList=elem.attributes();
                int attributeSize=attrivuteList.size();
                System.out.println(elementName+"有属性"+attributeSize+"个");
                for(int j=0;j<attributeSize;j++){
                    Attribute attribute=attrivuteList.get(j);
                    String attributeName=attribute.getName();
                    String attributeText=attribute.getText();
                    System.out.println(elementName+"有属性:"+attributeName+",其值为:"+attributeText);
                }
                analyzeElement(elem);
                System.out.println(elementName+"是元素Element");
            }else{
                String nodeText=node.getText();
                System.out.println(nodeText+"文本是节点Node");
            }
            System.out.println("-------------------");
        }
    }
}

在该示例中展示了利用DOM4J加载XML,并解析出XML中的元素和节点且获取出元素的名称,节点的文本,属性的值等等内容。在此,务必注意区分元素和节点;请切记:标签之间的空格换行也是一个节点!!!!至于,DOM4J的其他API在此不在依次举出。

当你看完这个例子,如果还不了解元素和节点的区别,请您参照w3school的教程

利用XPATH解析XML

XPATH的全称是Xml Path Language;专门用于查询XML中的数据。怎么查询呢?嗯哼,其实从它的全名可以就能看出点端倪了:该方式和路径是相关联的。

请看如下示例:

package cn.xml;

import java.util.List;
import org.dom4j.Document;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
import org.junit.Test;

/**
 * 本文作者:谷哥的小弟
 * 博客地址:http://blog.csdn.net/lfdfhl
 */
public class TestXPATH {    

    @Test
    public void testXPATH1() throws Exception{
        SAXReader read = new SAXReader();
        Document document = read.read("src/student.xml");
        Node node = document.selectSingleNode("/students/student[1]/name");
        String text=node.getText();
        System.out.println(text);
    }

    @Test
    public void TESTXPATH2() throws Exception{
        SAXReader read = new SAXReader();
        Document document = read.read("src/student.xml");
        List<Node> nodeList = document.selectNodes("//*");
        for (int i = 0; i < nodeList.size(); i++) {
            Node node = nodeList.get(i);
            String name=node.getName();
            String text=node.getText();
            System.out.println(name+"\t"+text);
        }
    }

}

现对该示例解析如下:

  • 查询单个学生的名字,请参见代码第19行
    在student.xml中一共有三个学生,在此获取第一个学生的名字
  • 获取student.xml中所有的节点,请参见代码第28行
  • 关于XPATH的更多规则请您参见XPathTutorial

JUnit单元测试

为测试方便,可用JUnit进行测试。比如写一个方法,将待测试的代码置于方法体内即可。在使用过程中,请注意:

  • 1、测试方法的返回值为void

  • 2、测试方法无输入参数

  • 3、测试方法需是public的

  • 4、利用Assert测试结果是否正确

示例如下:

package cn.com;

import junit.framework.Assert;
import org.junit.Test;
/**
 * 本文作者:谷哥的小弟
 * 博客地址:http://blog.csdn.net/lfdfhl
 */
public class TestJUnit {
    @Test
    public void test1(){
        int c=1+2;
        Assert.assertEquals(3, c);
    }

    @Test
    public void test2(){
        int c=1+2;
        Assert.assertEquals(4, c);
    }

}

最后,贴出项目结构图,如下所示:

这里写图片描述

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

分享:
开发与运维
使用钉钉扫一扫加入圈子
+ 订阅

集结各类场景实战经验,助你开发运维畅行无忧

其他文章