Java 操作 XML (2)--SAX 方式处理 XML

SAX 是一个用于处理XML事件驱动的“推”模型,虽然它不是W3C标准,但它却是一个得到了广泛认可的API。本文主要介绍 Java SAX 方式处理 XML,文中所使用到的软件版本:Java 1.8.0_191。

1、SAX 简介

      SAX 的全称是 Simple APIs for XML,也即 XML 简单应用程序接口。与DOM不同,SAX 提供的访问模式是一种顺序模式,这是一种快速读写 XML 数据的方式。当使用 SAX 分析器对 XML 文档进行分析时,会触发一系列事件,并激活相应的事件处理函数,应用程序通过这些事件处理函数实现对XML文档的访问,因而 SAX 接口也被称作事件驱动接口。

1.1、SAX 的优点

1、顺序读入文档并产生相应事件,可以处理任何大小的XML文档。
2、适用于只需要文档的部分内容,或者只需要从文档中得到特定信息。

1.2、SAX 的缺点

1、只能对文档按顺序解析一遍,不支持对文档的随意访问。
2、只能读取XML文档内容,而不能修改。
3、开发上比较复杂,需要自己来实现事件处理器。

2、Java SAX 方式操作 XML

2.1、XML 文件

<?xml version="1.0" encoding="utf-8" ?>
<school:grade xmlns:school="http://www.w3.org/TR/html4/school/">
    <school:student rollno="1" school:age="10">
        <school:firstname>cxx1</school:firstname>
        <lastname>Bob1</lastname>
        <nickname>stars1</nickname>
        <marks>85</marks>
    </school:student>
    <student rollno="2">
        <firstname>cxx2</firstname>
        <lastname>Bob2</lastname>
        <nickname>stars2</nickname>
        <marks>85</marks>
    </student>
    <student rollno="3">
        <firstname>cxx3</firstname>
        <lastname>Bob3</lastname>
        <nickname>stars3</nickname>
        <marks>85</marks>
    </student>
</school:grade>

2.2、Java 代码例子

该例子演示如何使用 SAX 方式解析 XML 以及使用 SAX 方式来生成 XML。

package com.abc.demo.general.xml;

import org.apache.commons.lang.StringUtils;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;
import org.xml.sax.helpers.DefaultHandler;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.sax.TransformerHandler;
import javax.xml.transform.stream.StreamResult;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.List;

public class SaxCase {
    private static Logger logger = LoggerFactory.getLogger(SaxCase.class);

    /**
     * 解析xml
     * @throws Exception
     */
    @Test
    public void parse() throws Exception {
        SAXParserFactory factory = SAXParserFactory.newInstance();
        SAXParser parser = factory.newSAXParser();
        SaxHandler handler = new SaxHandler();
        parser.parse(DomCase.class.getResourceAsStream("student.xml"), handler);
        logger.info(handler.getStudents().toString());
    }

    /**
     * 生成xml
     * @throws Exception
     */
    @Test
    public void toXml() throws Exception {
        //创建SAX转换工厂
        SAXTransformerFactory factory = (SAXTransformerFactory) SAXTransformerFactory.newInstance();
        TransformerHandler handler = factory.newTransformerHandler();

        //创建handler转换器
        Transformer transformer = handler.getTransformer();
        //换行
        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
        transformer.setOutputProperty(OutputKeys.ENCODING, "utf-8");

        ByteArrayOutputStream out = new ByteArrayOutputStream();
        StreamResult streamResult = new StreamResult(out);
        handler.setResult(streamResult);

        AttributesImpl attributes = new AttributesImpl();
        //打开doc对象
        handler.startDocument();
        handler.startElement("http://www.w3.org/TR/html4/school/", "", "school:class", null);

        //第一个学生
        attributes.clear();
        attributes.addAttribute("", "", "rollno", "", "1");
        attributes.addAttribute("", "", "school:age", "", "10");
        handler.startElement("", "", "student", attributes);
        handler.startElement("", "", "school:firstname", null);
        handler.characters("cxx1".toCharArray(), 0, 4);
        handler.endElement("", "", "school:firstname");
        handler.startElement("", "", "lastname", null);
        handler.characters("Bob1".toCharArray(), 0, 4);
        handler.endElement("", "", "lastname");
        handler.startElement("", "", "nickname", null);
        handler.characters("stars1".toCharArray(), 0, 6);
        handler.endElement("", "", "nickname");
        handler.startElement("", "", "marks", null);
        handler.characters("85".toCharArray(), 0, 2);
        handler.endElement("", "", "marks");
        handler.endElement("", "", "student");
        //第二个学生
        attributes.clear();
        attributes.addAttribute("", "", "rollno", "", "2");
        handler.startElement("", "", "student", attributes);
        handler.startElement("", "", "firstname", null);
        handler.characters("cxx2".toCharArray(), 0, 4);
        handler.endElement("", "", "firstname");
        handler.startElement("", "", "lastname", null);
        handler.characters("Bob2".toCharArray(), 0, 4);
        handler.endElement("", "", "lastname");
        handler.startElement("", "", "nickname", null);
        handler.characters("stars2".toCharArray(), 0, 6);
        handler.endElement("", "", "nickname");
        handler.startElement("", "", "marks", null);
        handler.characters("85".toCharArray(), 0, 2);
        handler.endElement("", "", "marks");
        handler.endElement("", "", "student");
        //第三个学生
        attributes.clear();
        attributes.addAttribute("", "", "rollno", "", "3");
        handler.startElement("", "", "student", attributes);
        handler.startElement("", "", "firstname", null);
        handler.characters("cxx3".toCharArray(), 0, 4);
        handler.endElement("", "", "firstname");
        handler.startElement("", "", "lastname", null);
        handler.characters("Bob3".toCharArray(), 0, 4);
        handler.endElement("", "", "lastname");
        handler.startElement("", "", "nickname", null);
        handler.characters("stars3".toCharArray(), 0, 6);
        handler.endElement("", "", "nickname");
        handler.startElement("", "", "marks", null);
        handler.characters("85".toCharArray(), 0, 2);
        handler.endElement("", "", "marks");
        handler.endElement("", "", "student");

        handler.endElement("", "", "school:class");

        handler.endDocument();
        logger.info(out.toString());
    }
}

class SaxHandler extends DefaultHandler {
    private String text;
    private static Logger logger = LoggerFactory.getLogger(SaxHandler.class);

    private List<Student> students = new ArrayList<>();
    private Student student = null;

    public List<Student> getStudents() {
        return students;
    }

    public SaxHandler() {}

    @Override
    public void startDocument() throws SAXException {
        super.startDocument();
        logger.info("SAX解析开始");
    }

    @Override
    public void endDocument() throws SAXException {
        super.endDocument();
        logger.info("SAX解析结束");
    }

    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        super.startElement(uri, localName, qName, attributes);
        logger.info("qName={}", qName);
        if (qName.equals("student") || qName.equals("school:student")) {
            student = new Student();
            students.add(student);

            student.setRollno(Integer.parseInt(attributes.getValue("rollno")));
            String age = attributes.getValue("school:age");
            if (StringUtils.isNotBlank(age)) {
                student.setAge(Integer.parseInt(age));
            }
        }
    }

    @Override
    public void endElement(String uri, String localName, String qName)
            throws SAXException {
        super.endElement(uri, localName, qName);
        if ("firstname".equals(qName) || "school:firstname".equals(qName) ) {
            student.setFirstname(text);
        } else if ("lastname".equals(qName)) {
            student.setLastname(text);
        } else if ("nickname".equals(qName)) {
            student.setNickname(text);
        } else if ("marks".equals(qName)) {
            student.setMarks(text);
        }
    }

    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        super.characters(ch, start, length);
        text = new String(ch, start, length);
    }
}

 Student 实体类:

package com.abc.demo.general.xml;

/**
 * 学生
 */
public class Student {
    private int rollno;
    private int age;
    private String firstname;
    private String lastname;
    private String nickname;
    private String marks;

    public Student() {}

    public Student(int rollno, int age, String firstname, String lastname, String nickname, String marks) {
        this.rollno = rollno;
        this.age = age;
        this.firstname = firstname;
        this.lastname = lastname;
        this.nickname = nickname;
        this.marks = marks;
    }

    public int getRollno() {
        return rollno;
    }

    public void setRollno(int rollno) {
        this.rollno = rollno;
    }

    public int getAge() {
        return age;
    }

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

    public String getFirstname() {
        return firstname;
    }

    public void setFirstname(String firstname) {
        this.firstname = firstname;
    }

    public String getLastname() {
        return lastname;
    }

    public void setLastname(String lastname) {
        this.lastname = lastname;
    }

    public String getNickname() {
        return nickname;
    }

    public void setNickname(String nickname) {
        this.nickname = nickname;
    }

    public String getMarks() {
        return marks;
    }

    public void setMarks(String marks) {
        this.marks = marks;
    }

    @Override
    public String toString() {
        return "Student{" +
                "rollno=" + rollno +
                ", age=" + age +
                ", firstname='" + firstname + '\'' +
                ", lastname='" + lastname + '\'' +
                ", nickname='" + nickname + '\'' +
                ", marks='" + marks + '\'' +
                '}';
    }
}
Student.java

 

posted @ 2020-12-12 10:48  且行且码  阅读(350)  评论(0编辑  收藏  举报