Java 之XML与JSON (SAM、DOM、JDOM和DOM4J解析的特点及区别)

SAM解析的特点
  • 1.基于事件驱动
  • 2.从上至下依次顺序读取,速度快
  • 3.不能任意读取节点,灵活性差
  • 4.解析时占用的内存小
  • 5.SAX更适用于在性能要求更高的设备上使用(Android开发中,等移动开发)
DOM解析XML
  • 1.基于树型结构,通过一次性把文档加载到内存中,所以会比较占用内存,可以随机访问更加灵活,更适合在Web开发中使用
JDOM解析XML
  • 1.与DOM类似基于树型结构
  • 2.与DOM区别
    (1)第三方开源组件
    (2)实现JAVA的Collection接口
    (3)效率比DOM更快
DOM4J解析XML
  • 1.基于树型结构,第三方组件
  • 2.解析速度快,效率高,使用的JAVA中的迭代器实现数据读取,在Web框架中使用较多(Hibernate)
四种方法比较
  • JDOM和DOM在性能测试时表现不佳,在测试10M文档时内存溢出。
  • SAX表现好,这主要依赖于它特定的解析方式。一个SAX检测即将到来的XML流,但并没有载入到内存中(当然当XML流读入时,会有部分文档暂时隐藏在内存中)。
  • DOM4J是这场测试的获胜者。目前许多开源项目中大量采用DOM4J,例如(Hibernate)也用DOM4J来读取XML配置文件

举例说明:
1.创建SAM、DOM、JDOM和DOM4J解析器工厂对象

package com.vince;

import org.dom4j.DocumentException;
import org.dom4j.io.SAXReader;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
import org.junit.Test;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import javax.xml.parsers.*;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Handler;

/**
 * 四种方法比较
 * JDOM和DOM在性能测试时表现不佳,在测试10M文档时内存溢出。
 * SAX表现好,这主要依赖于它特定的解析方式。一个SAX检测即将到来的XML流,但并没有载入到内存中(当然当XML流读入时,会有部分文档暂时隐藏在内存中)。
 *
 * DOM4J是这场测试的获胜者。目前许多开源项目中大量采用DOM4J,例如(Hibernate)也用DOM4J来读取XML配置文件
 *
 *
 */

public class XMLDemo {
    /**
     *DOM4J解析XML
     * 1.基于树型结构,第三方组件
     * 2.解析速度快,效率高,使用的JAVA中的迭代器实现数据读取,在Web框架中使用较多(Hibernate)
     */

    @Test
    public void dom4jParseXML() throws DocumentException {
        //1.创建DOM4J的解析对象
        SAXReader reader=new SAXReader();
        InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("com/vince/Person.xml");
        org.dom4j.Document doc = reader.read(is);
        org.dom4j.Element rootElement = doc.getRootElement();
        Iterator<org.dom4j.Element> iterator=rootElement.elementIterator();
        ArrayList<Person> persons = new ArrayList<>();
        Person p=null;
        while(iterator.hasNext()){
            p=new Person();
          org.dom4j.Element e=iterator.next();
          p.setPersonid(e.attributeValue("personid"));
          Iterator<org.dom4j.Element> iterator1 = e.elementIterator();
          while (iterator1.hasNext()){
              org.dom4j.Element next = iterator1.next();
              String tag = next.getName();
              if("name".equals(tag)){
                  p.setName(next.getText());
              }else if ("address".equals(tag)){
                  p.setAddress(next.getText());
              }else if ("tel".equals(tag)){
                  p.setTel(next.getText());
              }else if ("fax".equals(tag)){
                  p.setFax(next.getText());
              }else if ("email".equals(tag)){
                  p.setEmail(next.getText());
              }
          }
          persons.add(p);
        }
        System.out.println("结果:");
        System.out.println(Arrays.toString(persons.toArray()));

    }

    /**
     *JDOM解析XML
     * 1.与DOM类似基于树型结构
     * 2.与DOM区别
     *  (1)第三方开源组件
     *  (2)实现JAVA的Collection接口
     *  (3)效率比DOM更快
     */

    @Test
    public void jdomParseXML() throws JDOMException, IOException {
        //创建JDOM解析器
        SAXBuilder builder=new SAXBuilder();
        InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("com/vince/Person.xml");
        org.jdom2.Document build = builder.build(is);
        Element rootElement = build.getRootElement();
        List<Person> list=new ArrayList<>();
        Person person=null;
        List<Element> children = rootElement.getChildren();
        for (Element element:children){
            person=new Person();
            String personid = element.getAttributeValue("personid");
            person.setPersonid(personid);
            List<Element> children1 = element.getChildren();
            for (Element e:children1){
                String tag = e.getName();
                if("name".equals(tag)){
                    person.setName(e.getText());
                }else if ("address".equals(tag)){
                    person.setAddress(e.getText());
                }else if ("tel".equals(tag)){
                    person.setTel(e.getText());
                }else if ("fax".equals(tag)){
                    person.setFax(e.getText());
                }else if ("email".equals(tag)){
                    person.setEmail(e.getText());
                }
            }
            list.add(person);
        }
        System.out.println("结果:");
        System.out.println(Arrays.toString(list.toArray()));


    }

    /**
     *DOM解析XML
     * 1.基于树型结构,通过一次性吧文档加载到内存中,所以会比较占用内存,可以随机访问更加灵活,更适合在Web开发中使用
     *
     */

    @Test
    public void domParseXML() throws ParserConfigurationException, IOException, SAXException {
        //1.创建一个DOM解析器工厂对象
        DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
        //2.通过工厂对象创建DOM解析器
        DocumentBuilder documentBuilder=factory.newDocumentBuilder();
        //3.解析文档
        InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("com/vince/Person.xml");

        Document doc=documentBuilder.parse(is);
        //4.从内存中读取数据

        //获取节点名称为person的所有节点
        NodeList personNodeList = doc.getElementsByTagName("person");
        ArrayList<Person> persons = new ArrayList<>();
        Person p;
        int length=personNodeList.getLength();
        //此循环会迭代两次
        for (int i=0;i<length;i++){
            Node personNode = personNodeList.item(i);
            p=new Person();
            String personid = personNode.getAttributes().getNamedItem("personid").getNodeValue();
            p.setPersonid(personid);
            //获取当前结点的所有的子节点
            NodeList childNodes = personNode.getChildNodes();
            for (int j=0;j<childNodes.getLength();j++){
                Node item = childNodes.item(j);
                String nodeName = item.getNodeName();
                if("name".equals(nodeName)){
                    p.setName(item.getFirstChild().getNodeValue());
                }else if("address".equals(nodeName)){
                    p.setAddress(item.getFirstChild().getNodeValue());
                }else if("tel".equals(nodeName)){
                    p.setTel(item.getFirstChild().getNodeValue());
                }else if("fax".equals(nodeName)){
                    p.setFax(item.getFirstChild().getNodeValue());
                }else if("email".equals(nodeName)){
                    p.setEmail(item.getFirstChild().getNodeValue());
                }

            }
            persons.add(p);

        }
        System.out.println("结果:");
        System.out.println(Arrays.toString(persons.toArray()));
    }


    @Test
    public void saxParseXML() throws ParserConfigurationException, SAXException, IOException {
        //1.创建一个SAX解析器工厂对象
        SAXParserFactory saxParserFactory=SAXParserFactory.newInstance();
        //2.通过工厂对象创建SAX解析器
        SAXParser saxParser=saxParserFactory.newSAXParser();
        //3.创建一个数据处理器(自己编写)
        PersonHandler personHandler = new PersonHandler();
        //4.开始解析
        InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("com/vince/Person.xml");
        saxParser.parse(is, personHandler);
        List<Person> persons = personHandler.getPersons();
        for(Person p:persons){
            System.out.println(p);
        }

    }
}


2.创建Person类

package com.vince;

public class Person {
    private String personid;
    private String name;
    private String address;
    private String tel;
    private String fax;
    private String email;

    public String getPersonid() {
        return personid;
    }

    public void setPersonid(String personid) {
        this.personid = personid;
    }

    public String getName() {
        return name;
    }

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

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getTel() {
        return tel;
    }

    public void setTel(String tel) {
        this.tel = tel;
    }

    public String getFax() {
        return fax;
    }

    public void setFax(String fax) {
        this.fax = fax;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    @Override
    public String toString() {
        return "Person{" +
                "personid='" + personid + '\'' +
                ", name='" + name + '\'' +
                ", address='" + address + '\'' +
                ", tel='" + tel + '\'' +
                ", fax='" + fax + '\'' +
                ", email='" + email + '\'' +
                '}';
    }
}

3.创建SAM的PersonHandler控制器

package com.vince;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import java.util.ArrayList;
import java.util.List;

/**
 * SAM解析的特点
 * 1.基于事件驱动
 * 2.从上至下依次顺序读取,速度快
 * 3.不能任意读取节点,灵活性差
 * 4.解析时占用的内存小
 * 5.SAX更适用于在性能要求更高的设备上使用(Android开发中,等移动开发)
 */
public class PersonHandler extends DefaultHandler {
    private List<Person> persons;
    private Person p;//当前正在解析的Person
    private String tag;//用于几率当前正在解析的标签名

    public List<Person> getPersons() {
        return persons;
    }

    //开始解析文档时调用
    @Override
    public void startDocument() throws SAXException {
        super.startDocument();
        persons=new ArrayList<>();
        System.out.println("开始解析文档");
    }
//在XML文档解析结束时当用
    @Override
    public void endDocument() throws SAXException {
        super.endDocument();
        System.out.println("解析文档结束。");
    }
//解析开始元素时调用(标签)
    /**
     *
     * @param uri
     * @param localName    不带前缀的标签名
     * @param qName        带前缀的标签名
     * @param attributes   当前标签的属性集合
     * @throws SAXException
     */
    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        super.startElement(uri, localName, qName, attributes);
        if("person".equals(qName)){
            p=new Person();
            String personid = attributes.getValue("personid");
            p.setPersonid(personid);
        }
        tag=qName;
        //System.out.println("startElement--"+qName); 测试
    }
//解析结束元素时调用(标签)
    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        super.endElement(uri, localName, qName);
        if("person".equals(qName)){
            persons.add(p);
        }
        tag=null;
        //System.out.println("endElement--"+qName);测试
    }
//解析文本内容时调用
    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        super.characters(ch, start, length);
        if (tag != null) {
          if ("name".equals(tag)) {
                p.setName(new String(ch,start,length));
            }else if ("address".equals(tag)){
                p.setAddress(new String(ch,start,length));
            }else if("tel".equals(tag)){
              p.setTel(new String(ch,start,length));
          }else if("fax".equals(tag)){
              p.setFax(new String(ch,start,length));
          }else if("email".equals(tag)){
              p.setEmail(new String(ch,start,length));
          }
            //System.out.println(ch);测试
        }
    }
}

4.使用xml文档

<?xml version="1.0" encoding="UTF-8"?>
<people>
    <person personid="E01">
        <name>Tony Blair</name>
        <address>10 Downing Street,London,UK</address>
        <tel>(061) 987654</tel>
        <fax>(061) 987654</fax>
        <email>blair@ererywhere.com</email>
    </person>
    <person personid="E02">
        <name>Bili Clinton</name>
        <address>White House,USA</address>
        <tel>(001) 6400 987654</tel>
        <fax>(001) 6400 987654</fax>
        <email>bili@ererywhere.com</email>
    </person>
</people>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值