• Java&Xml教程(五)使用SAX方式解析XML文件


    Java SAX解析机制为我们提供了一系列的API来处理XML文件,SAX解析和DOM解析方式不太一样,它并不是將XML文件内容一次性全部加载,而是连续的部分加载。

    javax.xml.parsers.SAXParser类提供了一些函数,采用事件处理方式解析XML文档,这个类实现了XMLReader接口,提供了重载的parse()方法从File,InputStream,SAX InputSource和URI字符串中读取XML文档。
    实际的XML解析工作由Handler类来完成,我们需要创建自己的Handler类,这就需要我们实现org.xml.sax.ContentHandler接口。这个接口中包含当事件发生时接收通知的回调方法,例如 StartDocument, EndDocument, StartElement, EndElement, CharacterData等等。

    org.xml.sax.helpers.DefaultHandler提供了ContentHandler接口的默认实现,因此我们可以继承该类实现自己的处理类。继承这个类是明智的选择,因为我们可能只需要实现一些方法。继承这个类可以保证代码的简洁和可维护性。
    下面是我们要解析的XML文档:
    employees.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <Employees>
        <Employee id="1">
            <age>29</age>
            <name>Pankaj</name>
            <gender>Male</gender>
            <role>Java Developer</role>
        </Employee>
        <Employee id="2">
            <age>35</age>
            <name>Lisa</name>
            <gender>Female</gender>
            <role>CEO</role>
        </Employee>
        <Employee id="3">
            <age>40</age>
            <name>Tom</name>
            <gender>Male</gender>
            <role>Manager</role>
        </Employee>
        <Employee id="4">
            <age>25</age>
            <name>Meghna</name>
            <gender>Female</gender>
            <role>Manager</role>
        </Employee>
    </Employees>

    该XML文件内容存放一些员工的信息,每个员工包含id属性和age, name, gender,role字段。
    我们將使用SAX解析机制处理XML文件并创建员工对象列表。
    我们使用Employee类抽象员工的信息:Employee.java

    package com.journaldev.xml;
    
    public class Employee {
        private int id;
        private String name;
        private String gender;
        private int age;
        private String role;
    
        public int getId() {
            return id;
        }
        public void setId(int id) {
            this.id = id;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public String getGender() {
            return gender;
        }
        public void setGender(String gender) {
            this.gender = gender;
        }
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
        public String getRole() {
            return role;
        }
        public void setRole(String role) {
            this.role = role;
        }
    
        @Override
        public String toString() {
            return "Employee:: ID="+this.id+" Name=" + this.name + " Age=" + this.age + " Gender=" + this.gender +
                    " Role=" + this.role;
        }
    
    }

    接着继承DefaultHandler类创建自己的Handler类MyHandler.java

    package com.journaldev.xml.sax;
    
    
    import java.util.ArrayList;
    import java.util.List;
    
    import org.xml.sax.Attributes;
    import org.xml.sax.SAXException;
    import org.xml.sax.helpers.DefaultHandler;
    
    import com.journaldev.xml.Employee;
    
    
    public class MyHandler extends DefaultHandler {
    
        //List to hold Employees object
        private List<Employee> empList = null;
        private Employee emp = null;
    
    
        //getter method for employee list
        public List<Employee> getEmpList() {
            return empList;
        }
    
    
        boolean bAge = false;
        boolean bName = false;
        boolean bGender = false;
        boolean bRole = false;
    
    
        @Override
        public void startElement(String uri, String localName, String qName, Attributes attributes)
                throws SAXException {
    
            if (qName.equalsIgnoreCase("Employee")) {
                //create a new Employee and put it in Map
                String id = attributes.getValue("id");
                //initialize Employee object and set id attribute
                emp = new Employee();
                emp.setId(Integer.parseInt(id));
                //initialize list
                if (empList == null)
                    empList = new ArrayList<>();
            } else if (qName.equalsIgnoreCase("name")) {
                //set boolean values for fields, will be used in setting Employee variables
                bName = true;
            } else if (qName.equalsIgnoreCase("age")) {
                bAge = true;
            } else if (qName.equalsIgnoreCase("gender")) {
                bGender = true;
            } else if (qName.equalsIgnoreCase("role")) {
                bRole = true;
            }
        }
    
    
        @Override
        public void endElement(String uri, String localName, String qName) throws SAXException {
            if (qName.equalsIgnoreCase("Employee")) {
                //add Employee object to list
                empList.add(emp);
            }
        }
    
    
        @Override
        public void characters(char ch[], int start, int length) throws SAXException {
    
            if (bAge) {
                //age element, set Employee age
                emp.setAge(Integer.parseInt(new String(ch, start, length)));
                bAge = false;
            } else if (bName) {
                emp.setName(new String(ch, start, length));
                bName = false;
            } else if (bRole) {
                emp.setRole(new String(ch, start, length));
                bRole = false;
            } else if (bGender) {
                emp.setGender(new String(ch, start, length));
                bGender = false;
            }
        }
    }

    MyHandler类持有一个存放Employee对象的List引用,它只有一个对应的getter方法。Employee对象在事件处理函数中被添加到List对象,在MyHandler类中还定义了Employee对象和它的几个字段相关的boolean类型变量用于创建Employee对象,当Employee对象的所有属性都被设置时,它就会被添加到list中。
    我们重写了几个重要的方法startElement(), endElement() 和characters().
    当SAXParser 开始解析文档时遇到元素的开始标签时,startElement() 方法就会被调用,我们重写了这个方法,使用boolean类型变量来区分元素类别。我们也是在该方法中,当Employee 标签开始时创建Employee 对象。
    当SAXParser遇到元素中的字符串数据时characters()方法会被调用,我们使用boolean类型字段为Employee对象的属性进行赋值。
    endElement()方法则会在SAXParser 遇到XML结束标签时会被调用,在这里我们將Employee对象添加到List对象中。
    在下面的测试程序中,我们使用MyHandler解析XML文档生成存放Employee 对象List。
    XMLParserSAX.java

    package com.journaldev.xml.sax;
    
    import java.io.File;
    import java.io.IOException;
    import java.util.List;
    
    import javax.xml.parsers.ParserConfigurationException;
    import javax.xml.parsers.SAXParser;
    import javax.xml.parsers.SAXParserFactory;
    
    import org.xml.sax.SAXException;
    
    import com.journaldev.xml.Employee;
    
    public class XMLParserSAX {
    
        public static void main(String[] args) {
        SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
        try {
            SAXParser saxParser = saxParserFactory.newSAXParser();
            MyHandler handler = new MyHandler();
            saxParser.parse(new File("/Users/pankaj/employees.xml"), handler);
            //Get Employees list
            List<Employee> empList = handler.getEmpList();
            //print employee information
            for(Employee emp : empList)
                System.out.println(emp);
        } catch (ParserConfigurationException | SAXException | IOException e) {
            e.printStackTrace();
        }
        }
    
    }

    运行程序输出:

    Employee:: ID=1 Name=Pankaj Age=29 Gender=Male Role=Java Developer
    Employee:: ID=2 Name=Lisa Age=35 Gender=Female Role=CEO
    Employee:: ID=3 Name=Tom Age=40 Gender=Male Role=Manager
    Employee:: ID=4 Name=Meghna Age=25 Gender=Female Role=Manager

    SAXParserFactory 类提供了工厂方法来获取SAXParser 实例,在调用 SAXParser对象的parse方法时传入Handler对象来处理回调事件。SAXParser解析机制刚开始接触时有点复杂,但是当你致力于处理大型的XML文档时,它比DOM解析提供了更有效的解析机制。
    原文地址:http://www.journaldev.com/1198/java-sax-parser-example-tutorial-to-parse-xml-to-list-of-objects

  • 相关阅读:
    Android 摇一摇之双甩功能
    Android 上千张图片的列表滑动加载
    Android 新手引导
    Android 自定义列表指示器
    Mininet的安装与卸载
    ubuntu装机必备
    linux系统中利用vagrant创建虚拟开发环境
    Ubuntu右键添加:open in terminal
    ryu启动问题总结
    新建WORD文档打开会出现转换文件对话框3步解决办法
  • 原文地址:https://www.cnblogs.com/lanzhi/p/6468387.html
Copyright © 2020-2023  润新知