SAX 解析器与 DOM 解析器不同,因为它不会将完整的 XML 加载到内存中,并连续阅读 xml 文档。
萨克斯帕塞尔
javax.xml.parsers.SAXParser
provides method to parse XML document using event handlers. This class implements XMLReader
interface and provides overloaded versions of parse()
methods to read XML document from File, InputStream, SAX InputSource and String URI. The actual parsing is done by the Handler class. We need to create our own handler class to parse the XML document. We need to implement org.xml.sax.ContentHandler
interface to create our own handler classes. This interface contains callback methods that receive notification when an event occurs. For example StartDocument, EndDocument, StartElement, EndElement, CharacterData etc. org.xml.sax.helpers.DefaultHandler
provides default implementation of ContentHandler interface and we can extend this class to create our own handler. It's advisable to extend this class because we might need only a few of the methods to implement. Extending this class will keep our code cleaner and maintainable.
Sax Parser 示例
现在让我们跳到SAX分析器示例程序,我将在稍后详细解释不同的功能。
1<?xml version="1.0" encoding="UTF-8"?>
2<Employees>
3 <Employee id="1">
4 <age>29</age>
5 <name>Pankaj</name>
6 <gender>Male</gender>
7 <role>Java Developer</role>
8 </Employee>
9 <Employee id="2">
10 <age>35</age>
11 <name>Lisa</name>
12 <gender>Female</gender>
13 <role>CEO</role>
14 </Employee>
15 <Employee id="3">
16 <age>40</age>
17 <name>Tom</name>
18 <gender>Male</gender>
19 <role>Manager</role>
20 </Employee>
21 <Employee id="4">
22 <age>25</age>
23 <name>Meghna</name>
24 <gender>Female</gender>
25 <role>Manager</role>
26 </Employee>
27</Employees>
因此,我们有一个 XML 文件存储在文件系统中的某个地方,通过查看它,我们可以得出结论,它包含员工列表. 每个员工都有id
属性和字段年龄
,名称
,性别
和角色
。
1package com.journaldev.xml;
2
3public class Employee {
4 private int id;
5 private String name;
6 private String gender;
7 private int age;
8 private String role;
9
10 public int getId() {
11 return id;
12 }
13 public void setId(int id) {
14 this.id = id;
15 }
16 public String getName() {
17 return name;
18 }
19 public void setName(String name) {
20 this.name = name;
21 }
22 public String getGender() {
23 return gender;
24 }
25 public void setGender(String gender) {
26 this.gender = gender;
27 }
28 public int getAge() {
29 return age;
30 }
31 public void setAge(int age) {
32 this.age = age;
33 }
34 public String getRole() {
35 return role;
36 }
37 public void setRole(String role) {
38 this.role = role;
39 }
40
41 @Override
42 public String toString() {
43 return "Employee:: ID="+this.id+" Name=" + this.name + " Age=" + this.age + " Gender=" + this.gender +
44 " Role=" + this.role;
45 }
46
47}
让我们创建自己的 SAX Parser Handler 类,扩展到 DefaultHandler类。
1package com.journaldev.xml.sax;
2
3import java.util.ArrayList;
4import java.util.List;
5
6import org.xml.sax.Attributes;
7import org.xml.sax.SAXException;
8import org.xml.sax.helpers.DefaultHandler;
9
10import com.journaldev.xml.Employee;
11
12public class MyHandler extends DefaultHandler {
13
14 // List to hold Employees object
15 private List<Employee> empList = null;
16 private Employee emp = null;
17 private StringBuilder data = null;
18
19 // getter method for employee list
20 public List<Employee> getEmpList() {
21 return empList;
22 }
23
24 boolean bAge = false;
25 boolean bName = false;
26 boolean bGender = false;
27 boolean bRole = false;
28
29 @Override
30 public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
31
32 if (qName.equalsIgnoreCase("Employee")) {
33 // create a new Employee and put it in Map
34 String id = attributes.getValue("id");
35 // initialize Employee object and set id attribute
36 emp = new Employee();
37 emp.setId(Integer.parseInt(id));
38 // initialize list
39 if (empList == null)
40 empList = new ArrayList<>();
41 } else if (qName.equalsIgnoreCase("name")) {
42 // set boolean values for fields, will be used in setting Employee variables
43 bName = true;
44 } else if (qName.equalsIgnoreCase("age")) {
45 bAge = true;
46 } else if (qName.equalsIgnoreCase("gender")) {
47 bGender = true;
48 } else if (qName.equalsIgnoreCase("role")) {
49 bRole = true;
50 }
51 // create the data container
52 data = new StringBuilder();
53 }
54
55 @Override
56 public void endElement(String uri, String localName, String qName) throws SAXException {
57 if (bAge) {
58 // age element, set Employee age
59 emp.setAge(Integer.parseInt(data.toString()));
60 bAge = false;
61 } else if (bName) {
62 emp.setName(data.toString());
63 bName = false;
64 } else if (bRole) {
65 emp.setRole(data.toString());
66 bRole = false;
67 } else if (bGender) {
68 emp.setGender(data.toString());
69 bGender = false;
70 }
71
72 if (qName.equalsIgnoreCase("Employee")) {
73 // add Employee object to list
74 empList.add(emp);
75 }
76 }
77
78 @Override
79 public void characters(char ch[], int start, int length) throws SAXException {
80 data.append(new String(ch, start, length));
81 }
82}
MyHandler 包含员工
对象的列表,作为一个只使用 getter 方法的字段。在事件处理方法中添加了员工
对象。
SAX 解析方法 解析方法
SAXParser
开始解析文档,当发现任何起始元素时,称为startElement()
方法。我们正在解析这种方法,以设定将用于识别元素的Boolean变量。我们也使用这种方法创建新的员工对象,每次找到员工开始元素。 检查ID属性如何在这里读取以设置员工对象id
字段。 当 SAXParser在元素中找到字符数据时,称为characters()
方法。 请注意,SAX分析师可能会将数据分成多个片段,并使用Callcharacters()
方法多次(读取ContentHandler字符类类()方法文档)。 这就是为什么我们正在使用StringBuilder来使用这个数据使用append()方法来保持这个数据。 Element Build
是我们
1package com.journaldev.xml.sax;
2
3import java.io.File;
4import java.io.IOException;
5import java.util.List;
6
7import javax.xml.parsers.ParserConfigurationException;
8import javax.xml.parsers.SAXParser;
9import javax.xml.parsers.SAXParserFactory;
10
11import org.xml.sax.SAXException;
12
13import com.journaldev.xml.Employee;
14
15public class XMLParserSAX {
16
17 public static void main(String[] args) {
18 SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
19 try {
20 SAXParser saxParser = saxParserFactory.newSAXParser();
21 MyHandler handler = new MyHandler();
22 saxParser.parse(new File("/Users/pankaj/employees.xml"), handler);
23 //Get Employees list
24 List<Employee> empList = handler.getEmpList();
25 //print employee information
26 for(Employee emp : empList)
27 System.out.println(emp);
28 } catch (ParserConfigurationException | SAXException | IOException e) {
29 e.printStackTrace();
30 }
31 }
32
33}
以下是上述方案的结果。
1Employee:: ID=1 Name=Pankaj Age=29 Gender=Male Role=Java Developer
2Employee:: ID=2 Name=Lisa Age=35 Gender=Female Role=CEO
3Employee:: ID=3 Name=Tom Age=40 Gender=Male Role=Manager
4Employee:: ID=4 Name=Meghna Age=25 Gender=Female Role=Manager
「SAXParserFactory」提供工厂方法来获取「SAXParser」实例. 我们正在将文件对象传输到分析方法以及MyHandler实例来处理回调事件。SAXParser在开始时有点困惑,但如果你正在处理一个大型XML文档,它提供了比DOM Parser更有效的方式来读取XML。
您可以从我们的 GitHub 存储库下载该项目。
Reference: SAXParser, DefaultHandler