SAX解析XML
SAX解析XML
1.XML(Extensible Markup Language 可扩展标记语言),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>qijingjing01@126.com</email>
</person>
<person personId="E02">
<name>Tony Blair</name>
<address>10 Downing Street,London,UK</address>
<tel>(061) 98765</tel>
<fax>(061) 98765</fax>
<email>qijingjing01@126.com</email>
</person>
</people>
2.XML的用途
(1)充当显示数据(以XML充当显示层)
(2)存储数据(存储层)的功能
(3)以XML描述数据,并在联系服务器与系统的其余部分之间传递
从某种角度讲,XML是数据封装和信息传递技术。
3.什么是SAX?
SAX是Simple Apl for XML的缩写
SAX是读取和操作XML数据更快捷,更轻量的方法,SAX允许你在读取文档时处理它,从而不必等待整个文档被存储后才采取操作,它不涉及DOM所必须得开销和概念跳跃,SAX api是一个基于事件的API ,适用于处理数据流,即随着数据的流动而一依次处理数据。SAX API在其解析你的文档时发生一定事件的时候会通知你,在你对其响应时,你不作保存的数据会被抛弃
SAX API中主要有四种处理事件的接口,ContenHandler、DTDHandler、EntiyResolver和ErrorHandler,由于DefaultHandler实现了这四个事件处理器接口。所以我们只需要继承DefaultHandler类就可以。
4.解析步骤
- 首先,我们把XML文件对应的Person写出来
package com.lili.xmlAndJson;
/**
* @author: QiJingJing
* @create: 2021/7/17
*/
public class Person {
private String personId;
private String name;
private String address;
private String tel;
private String fax;
private String email;
public Person(){}
public Person(String personId, String name, String address, String tel, String fax, String email) {
this.personId = personId;
this.name = name;
this.address = address;
this.tel = tel;
this.fax = fax;
this.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;
}
@Override
public String toString() {
return "Person{" +
"personId='" + personId + '\'' +
", name='" + name + '\'' +
", address='" + address + '\'' +
", tel='" + tel + '\'' +
", fax='" + fax + '\'' +
", email='" + email + '\'' +
'}';
}
}
-
在测试类里面创建SAX解析器工厂对象
// 1.创建一个SAX解析器工厂对象 SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
-
使用解析器工厂创建解析器实例
//2.通过工厂对象创建SAX解析器
SAXParser saxParser = saxParserFactory.newSAXParser();
-
写一个事件侦听器类,需要继承DefaultHandler类,然后重写其中五个方法,每个方法的用途我已经标注
package com.lili.xmlAndJson; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; import java.util.ArrayList; import java.util.List; /** * @author: QiJingJing * @create: 2021/7/17 */ public class PersonHandler extends DefaultHandler { private List<Person> personList; private Person p; // 当前正在解析的对象 private String tag;//用于记录当前正在解析的标签名 public List<Person> getPersonList() { return personList; } // 开始解析文档时调用 @Override public void startDocument() throws SAXException { super.startDocument(); personList = new ArrayList<>(); System.out.println("开始解析文档"); } @Override public void endDocument() throws SAXException { super.endDocument(); System.out.println("解析文档结束"); } // 解析开始元素时使用 /** * @param uri 命名空间 * @param localName 不带前缀的标签名 * @param qName 带前缀的标签名 * @param attributes 当前标签的属性集合 * @return: void * @author: QijingJing * @date: 2021/7/17 */ @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; } // 解析结束元素时使用 @Override public void endElement(String uri, String localName, String qName) throws SAXException { super.endElement(uri, localName, qName); if ("person".equals(qName)) { personList.add(p); } tag = null; } // 解析文本内容时调用 @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)); } } } }
-
在测试类里面创建一个侦听器对象,给出XML的地址,然后开始解析
package com.lili.xmlAndJson; import org.junit.Test; import org.xml.sax.SAXException; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import java.io.IOException; import java.io.InputStream; import java.util.List; /** * @author: QiJingJing * @create: 2021/7/17 */ public class XmlTest { @Test public void test() 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/lili/xmlAndJson/person.xml"); saxParser.parse(is,personHandler); List<Person> personList = personHandler.getPersonList(); personList.forEach(System.out::println); } }
输出如下:
开始解析文档
解析文档结束
Person{personId='E01', name='Tony Blair', address='10 Downing Street,London,UK', tel='(061) 98765', fax='(061) 98765', email='qijingjing01@126.com'}
Person{personId='E02', name='Tony Blair', address='10 Downing Street,London,UK', tel='(061) 98765', fax='(061) 98765', email='qijingjing01@126.com'}
Process finished with exit code 0
SAX解析的特点:
1.基于事件驱动
2.顺序读取,速度快
3.不能任意读取节点(灵活性差)
4.解析占用内存小
5.SAX更适用于在性能要求更高的设备上使用(Android开发中)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!