文章目录
  1. 1. XML
  2. 2. People
  3. 3. DOM
  4. 4. SAX
  5. 5. PULL
  6. 6. DOM和SAX对比
    1. 6.1. SAX适于处理下面的问题
    2. 6.2. DOM适于处理下面的问题
  7. 7. SAX和PULL对比
    1. 7.1. 相似
    2. 7.2. 不同
  8. 8. 其他解析方式

XML现在已经成为一种通用的数据交换格式,它的平台无关性,语言无关性,系统无关性,给数据集成与交互带来了极大的方便。

XML在不同的语言里解析方式都是一样的,只不过实现的语法不同而已。基本的解析方式有两种,一种叫SAX,另一种叫DOM。SAX是基于事件流的解析,DOM是基于XML文档树结构的解析。下面就给大家介绍一下比较常见的XML解析方式。

XML

<?xml version="1.0" encoding="UTF-8"?>
<peoples>
    <people>
        <name>never</name>
        <age>23</age>
    </people>
    <people>
        <name>leo</name>
        <age>19</age>
    </people>
    <people>
        <name>dom</name>
        <age>30</age>
    </people>
</peoples>

People

public class People {
    private String name;
    private int age;

    public int getAge() {
        return age;
    }

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

    public String getName() {
        return name;
    }

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

    public People(String name, int age) {

        this.name = name;
        this.age = age;
    }

    public People() {
    }

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

DOM

DOM的全称是Document Object Model,也即文档对象模型。在应用程序中,基于DOM的XML分析器将一个XML文档转换成一个对象模型的集合(通常称DOM树),应用程序正是通过对这个对象模型的操作,来实现对XML文档数据的操作。通过DOM接口,应用程序可以在任何时候访问XML文档中的任何一部分数据,因此,这种利用DOM接口的机制也被称作随机访问机制。

public ArrayList<People> parserXml(String filePath) throws ParserConfigurationException, IOException, SAXException {
        ArrayList<People> list = new ArrayList<People>();

        // step 1: 获得dom解析器工厂(工作的作用是用于创建具体的解析器)
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

        // step 2:获得具体的dom解析器
        DocumentBuilder builder = factory.newDocumentBuilder();

        // step3: 解析一个xml文档,获得Document对象(根结点)
        Document document = builder.parse(new File(filePath));

        NodeList nList = document.getElementsByTagName("people");

        for(int i = 0; i<nList.getLength(); i++) {
            People people = new People();

            Element node = (Element) nList.item(i);
            people.setName(node.getElementsByTagName("name").item(0).getFirstChild().getNodeValue());
            people.setAge(Integer.parseInt(node.getElementsByTagName("age").item(0).getFirstChild().getNodeValue()));
            list.add(people);
        }

        return list;
    }

SAX

Simple API for XML,是事件驱动型XML解析的一个标准接口。SAX的工作原理简单地说就是对文档进行顺序扫描,当扫描到文档(document)开始与结束、元素(element)开始与结束、文档(document)结束等地方时通知事件处理函数,由事件处理函数做相应动作,然后继续同样的扫描,直至文档结束。

public class SAXTest {
    public static void main(String arg[]) throws ParserConfigurationException, SAXException, IOException {
        SAXParserFactory factory = SAXParserFactory.newInstance();
        SAXParser parser = factory.newSAXParser();

        PeopleSAX handler = new PeopleSAX();

        parser.parse("JavaPrepare/resource/people.xml", handler);

        ArrayList<People> peoples = handler.getPeoples();

        for(int i = 0; i < peoples.size(); i++) {
            System.out.println(peoples.get(i).toString());
        }
    }

}

class PeopleSAX extends DefaultHandler {
    private ArrayList<People> peoples;
    private People people;
    private String tag;

    public PeopleSAX() {
        super();
    }

    @Override
    public void startDocument() throws SAXException {
        peoples = new ArrayList<People>();
    }

    @Override
    public void endDocument() throws SAXException {
        super.endDocument();
    }

    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        if("people" .equals(localName)) {
            people = new People();
        }
        tag = localName;
    }

    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        if("people" .equals(localName)) {
            peoples.add(people);
            people = null;
        }
        tag = null;
    }

    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        if(tag != null) {
            String data = new String(ch, start, length);
            if("name" .equals(tag)) {
              people.setName(data);
            } else if("age" .equals(tag)) {
              people.setAge(new Integer(data));
            }
        }
    }

    public ArrayList<People> getPeoples() {
        return peoples;
    }

}

PULL

PULL解析器的运行方式和SAX解析器很相似,它提供了类似的事件,如:开始元素和结束元素,使用parser,next() 可以进入下一个元素并且触发相应的事件,事件将作为代码被发送,因此可以使用一个switch来对事件进行选择,然后进行相应的处理。当开始解析元素的时候,调用parser.nextText()方法可以获得下一个Text类型的元素。

Android中极力推荐xmlpull方式解析xml。xmlpull不仅可用在Android上同样也适用于javase,但在javase环境中需自己获取xmlpull所依赖的类库。

Tips:导入Jar包时,只需要导入基于xmlpull实现的包,比如kxml2等,否则不能正常运行。

XMLPULL API is available freely. You can download XmlPull API as tarball or zip file. We are also providing access to the latest API version via anonymous CVS.

However to use XMLPULL you will need download an implementation of XmlPull API.

实例:

public class PULLTest {
    public static void main(String arg[]) throws IOException, XmlPullParserException {
        PULLTest test = new PULLTest();
        ArrayList<People> peoples = test.getPeoples("JavaPrepare/resource/people.xml");
        for(int i = 0; i < peoples.size(); i++) {
            System.out.println(peoples.get(i).toString());
        }
    }

    public ArrayList<People> getPeoples(String path) throws XmlPullParserException, IOException {
        ArrayList<People> list = null;
        People people = null;

        XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
        factory.setNamespaceAware(true);
        XmlPullParser parser = factory.newPullParser();
        parser.setInput(new FileReader(path));

        int eventType = parser.getEventType();

        do {
            String node = parser.getName();
            if(eventType == parser.START_DOCUMENT) {
                list = new ArrayList<People>();
            } else if(eventType == parser.END_DOCUMENT) {

            } else if(eventType == parser.START_TAG) {
                if("people".equals(node)) {
                    people = new People();
                } else if("name".equals(node)) {
                    String name = parser.nextText();
                    people.setName(name);
                } else if("age".equals(node)) {
                    int age = Integer.parseInt(parser.nextText());
                    people.setAge(age);
                }
            } else if(eventType == parser.END_TAG) {
                if("people".equals(node)) {
                    list.add(people);
                    people = null;
                }
            } else if(eventType == parser.TEXT) {

            }
            eventType = parser.next();
        } while (eventType != parser.END_DOCUMENT);
        return list;
    }
}

DOM和SAX对比

SAX适于处理下面的问题

  1. 对大型文件进行处理;
  2. 只需要文件夹的部分内容,或者只需从文件中得到特定信息。
  3. 想建立自己的对象模型的时候。

DOM适于处理下面的问题

  1. 需要对文件进行修改;
  2. 需要随机对文件进行存取

SAX和PULL对比

相似

他们的相似性在运行方式上,均是基于事件的解析方式,Pull解析器也提供了类似SAX的事件,开始文档START_DOCUMENT和结束文档END_DOCUMENT,开始元素START_TAG和结束元素END_TAG,遇到元素内容TEXT等,但需要调用next() 方法提取它们(主动提取事件)。

不同

SAX解析器的工作方式是自动将事件推入注册的事件处理器进行处理,因此你不能控制事件的处理主动结束;而Pull解析器的工作方式为允许你的应用程序代码主动从解析器中获取事件,正因为是主动获取事件,因此可以在满足了需要的条件后不再获取事件,结束解析。这是他们主要的区别。

其他解析方式

还有很多解析xml的方法,比如DOM4J、JDOM等等。但其基本的解析方式包含两种,一种是事件驱动的(代表SAX),另一种方式是基于文档结构(代表DOM)。其他的只不过语法不一样而已。这里就不一一介绍啦。

文章目录
  1. 1. XML
  2. 2. People
  3. 3. DOM
  4. 4. SAX
  5. 5. PULL
  6. 6. DOM和SAX对比
    1. 6.1. SAX适于处理下面的问题
    2. 6.2. DOM适于处理下面的问题
  7. 7. SAX和PULL对比
    1. 7.1. 相似
    2. 7.2. 不同
  8. 8. 其他解析方式