欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java基础之XML介绍与SAX解析、DOM解析XML、JDOM解析、DOM4J解析、XMLEncoder与XMLDecoder的使用以及xstream工具的使用 189~195

程序员文章站 2022-07-14 16:59:19
...

目录
1、什么是XML
2、XML的用途
3、SAX解析XML
4、DOM解析XML
5、JDOM解析XML
6、DOM4J解析XML
7、通过对象生成XML文件
8、各种解析方法比较
9、JSON
10、GSON组件的使用
11、XML与JSON的比较


1、什么是XML

XML(Extensible Markup Language 可扩展标记语言),XML是一个以文本来描述数据的文档

一个XML文档示例:
<?xml version="1.0" encoding="UTF-8"?>
<people>
	<person personid="E01">
		<name>Tony</name>
		<address>10 Downing Street, London, UK</address>
		<tel>(061) 98765</tel>
		<fax>(061) 98765</fax>
		<email>aaa@qq.com</email>
	</person>
	<person personid="E02">
		<name>Bill</name>
		<address>White House, USA</address>
		<tel>(001) 6400 98765</tel>
		<fax>(001) 6400 98765</fax>
		<email>aaa@qq.com</email>
	</person>
</people>

2、XML的用途

XML技术的用途:

(1)充当显示数据(以XML充当显示层)
(2)存储数据(存储层)的功能
(3)以XML描述数据,并在联系服务器与系统的其余部分之间传递。(传输数据的一样格式)

从某种角度讲,XML是数据封装和消息传递技术


3、SAX解析XML

  • SAX是Simple API for XML的缩写
  • SAX 是读取和操作 XML 数据更快速、更轻量的方法。
  • SAX 允许您在读取文档时处理它,从而不必等待整个文档被存储之后才采取操作。
  • 它不涉及 DOM 所必需的开销和概念跳跃。
  • SAX API是一个基于事件的API ,适用于处理数据流,即随着数据的流动而依次处理数据。
  • SAX API 在其解析您的文档时发生一定事件的时候会通知您。在您对其响应时,您不作保存的数据将会被抛弃。

SAX API中主要有四种处理事件的接口,
它们分别是
ContentHandler,DTDHandler, EntityResolver 和 ErrorHandler
实际上只要继承DefaultHandler 类就可以,
DefaultHandler实现了这四个事件处理器接口,
然后提供了每个抽象方法的默认实现。

  • 创建SAX解析器工厂对象
    SAXParserFactory spf = SAXParserFactory.newInstance();
  • 使用解析器工厂创建解析器实例
    SAXParser saxParser = spf.newSAXParser();
  • 创建SAX解析器要使用的事件侦听器对象
    PersonHandler handler =
    new PersonHandler();
  • 开始解析文件
    saxParser.parse(
    new File(fileName), handler);

二、DOM解析XML

JAVA 解析 XML 通常有两种方式,DOM 和 SAX
DOM:Document Object Model(文档对象模型)
DOM的特性:

  • 定义一组 Java 接口,基于对象,
  • 与语言和平台无关将 XML 文档表示为树,
  • 在内存中解析和存储 XML 文档,
  • 允许随机访问文档的不同部分。

DOM解析XML
DOM的优点由于树在内存中是持久的,因此可以修改后更新。
它还可以在任何时候在树中上下导航,API使用起来也较简单。


解析步骤

DocumentBuilderFactory builder = DocumentBuilderFactory.newInstance();
DocumentBuilder db = builder.newDocumentBuilder();
db.parse("person.xml");
NodeList node_person = doc.getElementsByTagName("person");


5、JDOM解析XML

JDOM是两位著名的 Java 开发人员兼作者,Brett Mclaughlin 和 Jason Hunter 的创作成果, 2000 年初在类似于Apache协议的许可下,JDOM作为一个开放源代码项目正式开始研发了。

JDOM 简化了与 XML 的交互并且比使用 DOM 实现更快,JDOM 与 DOM 主要有两方面不同。首先,JDOM 仅使用具体类而不使用接口。这在某些方面简化了 API,但是也限制了灵活性。第二,API 大量使用了 Collections 类,简化了那些已经熟悉这些类的 Java 开发者的使用。
别忘记添加jar包

下载地址:
http://www.jdom.org/downloads/index.html


解析步骤:

1)SAXBuilder sax = new SAXBuilder();2)Document doc = sax.build(.);3)Element el = doc.getRootElement();4)List list = el.getChildren();5)遍历内容

6、DOM4J解析XML

dom4j是一个非常非常优秀的Java XML API,具有性能优异、功能强大和极端易用使用的特点,同时它也是一个开放源代码的软件,可以在SourceForge上找到它。在对主流的Java XML API进行的性能、功能和易用性的评测,dom4j无论在那个方面都是非常出色的。如今你可以看到越来越多的Java软件都在使用dom4j来读写XML,特别值得一提的是连Sun的JAXM也在用dom4j。这是必须使用的jar包, Hibernate用它来读写配置文件。
别忘记添加jar包
下载地址:
https://dom4j.github.io/


解析步骤:

1)SAXReader sax = new SAXReader();2)Document doc = sax.read(Thread.currentThread().getContextClassLoader()
          .getResourceAsStream("person.xml"));3)Element root = doc.getRootElement();4)Iterator iterator = root.elementIterator();5)遍历迭代器


8、各种解析方法比较

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

SAX对内存使用较小 如果不考虑灵活性或考虑较少 SAX在Android开发中常用
考虑灵活性 一般使用DOM系列

面试题 问 解析XML有几种模式
答 有SAX和DOM两种解析机制
而DOM这种机制又分为 DOM JDOM DOM4J三种
在解析大文档的时候 通常使用DOM4J 不容易出现内存溢出


7、通过对象生成XML文件

根据对象生成XML文档.
使用Java提供的java.beans.XMLEncoder和java.beans.XMLDecoder类。
这是JDK 1.4以后才出现的类

步骤:
(1)实例化XML编码器

XMLEncoder xmlEncoder = new XMLEncoder(new BufferedOutputStream(new FileOutputStream(new File(“a.xml”))));

(2)输出对象
(3)关闭


xstream 实现XML的转换


示例
首先一个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) 98765</tel>
        <fax>(061) 98765</fax>
        <email>aaa@qq.com</email>
    </person>
    <person personid="E02">
        <name>Bill Clinton</name>
        <address>White House, USA</address>
        <tel>(001) 6400 98765</tel>
        <fax>(001) 6400 98765</fax>
        <email>aaa@qq.com</email>
    </person>
</people>

然后实体类

package com.vince.xml;

/**
 * Created by vince on 2017/7/1.
 */
public class Person {
    private String personid;
    private String name;
    private String address;
    private String tel;
    private String fax;
    private String email;

    @Override
    public String toString() {
        return "Person{" +
                "personid='" + personid + '\'' +
                ", name='" + name + '\'' +
                ", address='" + address + '\'' +
                ", tel='" + tel + '\'' +
                ", fax='" + fax + '\'' +
                ", email='" + 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;
    }
}

然后写个测试类


  • SAX解析的特点:
  • 1、基于事件驱动
  • 2、顺序读取,速度快
  • 3、不能任意读取节点(灵活性差)
  • 4、解析时占用的内存小
  • 5、SAX更适用于在性能要求更高的设备上使用(Android开发中)
  • @throws ParserConfigurationException
  • @throws SAXException
  • @throws IOException

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

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

  • DOM4J解析XML
    • 基于树型结构,第三方组件
    • 解析速度快,效率更高,使用的JAVA中的迭代器实现数据读取,在WEB框架中使用较多(Hibernate)

package com.vince.xml;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.Xpp3DomDriver;
import com.thoughtworks.xstream.io.xml.Xpp3Driver;
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.print.Doc;
import javax.xml.parsers.*;
import java.beans.XMLDecoder;
import java.beans.XMLEncoder;
import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

/**
 * Created by vince on 2017/7/1.
 */
public class XMLDemo {


    /**
     * 使用第三方xstream组件实现XML的解析与生成
     */
    @Test
    public void xStream(){
        Person p = new Person();
        p.setPersonid("1212");
        p.setAddress("北京");
        p.setEmail("aaa@qq.com");
        p.setFax("6768789798");
        p.setTel("13838389438");
        p.setName("38");

        XStream xStream = new XStream(new Xpp3Driver());
        xStream.alias("person",Person.class);
        xStream.useAttributeFor(Person.class,"personid");
        String xml = xStream.toXML(p);
        System.out.println(xml);

        //解析XML
        Person person = (Person)xStream.fromXML(xml);
        System.out.println(person);
    }


    /**
     * 从XML文件中读取对象
     */
    @Test
    public void xmlDecoder() throws FileNotFoundException {
        BufferedInputStream in = new BufferedInputStream(new FileInputStream("test.xml"));
        XMLDecoder decoder = new XMLDecoder(in);
        Person p = (Person)decoder.readObject();
        System.out.println(p);
    }
    /**
     * 把对象转成XML文件写入
     */
    @Test
    public void xmlEncoder() throws FileNotFoundException {
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("test.xml"));
        XMLEncoder xmlEncoder = new XMLEncoder(bos);
        Person p = new Person();
        p.setPersonid("1212");
        p.setAddress("北京");
        p.setEmail("aaa@qq.com");
        p.setFax("6768789798");
        p.setTel("13838389438");
        p.setName("38");
        xmlEncoder.writeObject(p);
        xmlEncoder.close();
    }

    /**
     * DOM4J解析XML
     * 基于树型结构,第三方组件
     * 解析速度快,效率更高,使用的JAVA中的迭代器实现数据读取,在WEB框架中使用较多(Hibernate)
     *
     */
    @Test
    public void dom4jParseXML() throws DocumentException {
        //1 创建DOM4J的解析器对象
        SAXReader reader = new SAXReader();
        InputStream is = Thread.currentThread().getContextClassLoader()
                .getResourceAsStream("com/vince/xml/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/xml/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、通过工厂对象创建解析器对象
        DocumentBuilder documentBuilder = factory.newDocumentBuilder();
        //3、解析文档
        InputStream is = Thread.currentThread().getContextClassLoader()
                .getResourceAsStream("com/vince/xml/person.xml");
        //此代码完成后,整个XML文档已经被加载到内存中,以树状形式存储
        Document doc = documentBuilder.parse(is);
        //4、从内存中读取数据

        //获取节点名称为person的所有节点,返回节点集合
        NodeList personNodeList = doc.getElementsByTagName("person");
        ArrayList<Person> persons = new ArrayList<>();
        Person p = null;
        //此循环会迭代两次
        for (int i=0;i<personNodeList.getLength();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)) {
                	//将name下的值也看作了结点 又因为只有一个 即第一个 所以获取值的时候 获取name的第一个结点的值
                    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()));
    }


    /**
     * SAX解析的特点:
     * 1、基于事件驱动
     * 2、顺序读取,速度快
     * 3、不能任意读取节点(灵活性差)
     * 4、解析时占用的内存小
     * 5、SAX更适用于在性能要求更高的设备上使用(Android开发中)
     * @throws ParserConfigurationException
     * @throws SAXException
     * @throws IOException
     */
    @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/xml/person.xml");
        saxParser.parse(is,personHandler);
        List<Person> persons = personHandler.getPersons();
        for (Person p:persons){
            System.out.println(p);
        }
    }
}

自己编写数据处理器


  • SAX解析的特点:
  • 1、基于事件驱动
  • 2、顺序读取,速度快
  • 3、不能任意读取节点(灵活性差)
  • 4、解析时占用的内存小
  • 5、SAX更适用于在性能要求更高的设备上使用(Android开发中)
package com.vince.xml;

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

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

/**
 * Created by vince on 2017/7/1.
 * SAX解析的特点:
 * 1、基于事件驱动
 * 2、顺序读取,速度快
 * 3、不能任意读取节点(灵活性差)
 * 4、解析时占用的内存小
 * 5、SAX更适用于在性能要求更高的设备上使用(Android开发中)
 *
 */
public class PersonHandler extends DefaultHandler{
    private List<Person> persons = null;
    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);
        }
    }
}

继承的是第一个
Java基础之XML介绍与SAX解析、DOM解析XML、JDOM解析、DOM4J解析、XMLEncoder与XMLDecoder的使用以及xstream工具的使用 189~195

一 SAX解析XML
这个就是使用SAX解析XML的基本代码
Java基础之XML介绍与SAX解析、DOM解析XML、JDOM解析、DOM4J解析、XMLEncoder与XMLDecoder的使用以及xstream工具的使用 189~195
下一步就是编写数据解析器 完善PersonHandler
结果
Java基础之XML介绍与SAX解析、DOM解析XML、JDOM解析、DOM4J解析、XMLEncoder与XMLDecoder的使用以及xstream工具的使用 189~195
二 Dom解析的结果
Java基础之XML介绍与SAX解析、DOM解析XML、JDOM解析、DOM4J解析、XMLEncoder与XMLDecoder的使用以及xstream工具的使用 189~195
三 JDOM解析XML
注意导入jar包时 都是org.jdom2下的
Java基础之XML介绍与SAX解析、DOM解析XML、JDOM解析、DOM4J解析、XMLEncoder与XMLDecoder的使用以及xstream工具的使用 189~195
JDOM结果

Java基础之XML介绍与SAX解析、DOM解析XML、JDOM解析、DOM4J解析、XMLEncoder与XMLDecoder的使用以及xstream工具的使用 189~195
四 DOM4J解析XML
结果
Java基础之XML介绍与SAX解析、DOM解析XML、JDOM解析、DOM4J解析、XMLEncoder与XMLDecoder的使用以及xstream工具的使用 189~195
五 把对象转成XML文件写入Java基础之XML介绍与SAX解析、DOM解析XML、JDOM解析、DOM4J解析、XMLEncoder与XMLDecoder的使用以及xstream工具的使用 189~195
结果 看起来生成的XML文件有点乱 不是我们想要的那种 所以我们还有更简洁的方式对象写入XML文件 那就是xstream工具实现XML的转换
Java基础之XML介绍与SAX解析、DOM解析XML、JDOM解析、DOM4J解析、XMLEncoder与XMLDecoder的使用以及xstream工具的使用 189~195
六 从XML文件中读取对象
Java基础之XML介绍与SAX解析、DOM解析XML、JDOM解析、DOM4J解析、XMLEncoder与XMLDecoder的使用以及xstream工具的使用 189~195
七 使用XStream组件解析与生产XML文件
Java基础之XML介绍与SAX解析、DOM解析XML、JDOM解析、DOM4J解析、XMLEncoder与XMLDecoder的使用以及xstream工具的使用 189~195
结果 对象的包名 作为根结点 所有东西都当做子节点
Java基础之XML介绍与SAX解析、DOM解析XML、JDOM解析、DOM4J解析、XMLEncoder与XMLDecoder的使用以及xstream工具的使用 189~195
不想要这种结果 不想要包名 而且想要personid作为属性
则使用alias起名字 起别名
然后设置属性
Java基础之XML介绍与SAX解析、DOM解析XML、JDOM解析、DOM4J解析、XMLEncoder与XMLDecoder的使用以及xstream工具的使用 189~195
Java基础之XML介绍与SAX解析、DOM解析XML、JDOM解析、DOM4J解析、XMLEncoder与XMLDecoder的使用以及xstream工具的使用 189~195
解析
Java基础之XML介绍与SAX解析、DOM解析XML、JDOM解析、DOM4J解析、XMLEncoder与XMLDecoder的使用以及xstream工具的使用 189~195
看 很简单吧 这种使用xstream组件的方式几行代码就搞定了 适合在传输文件的时候使用
前面的两种SAX和DOM机制 适合自己解析文件 哪些东西要解析 哪些不想解析的时候用 可以任意的过滤 过滤想要的东西