一、XML基础
1.1 什么是XML
1.2 XML常见应用
二、XML语法
语法较多,建议先直接上手写案例,成功之后再回来当回顾学习用
一个XML文件主要包括以下几个部分:
三、SAX解析
XML解析方式主要有:
DOM(文档对象模型):将整个文件以树的结构存储到内存中,适合小文件,程序可读性高。
SAX(基于事件流的解析):省内存,程序可读性相比上述较差。
PULL(第三方jar包):也是基于事件流的解析
本次,我们只学习SAX和PULL两种方式
正式来学习SAX解析
Simple APIs for XML,XML简单应用程序接口,在javax.xml.parsers包中,SAX解析是JDK自带的解析方式,包括一组接口和类
3.1 sax解析原理:以事件驱动的方式解析,即找开始结束标签的方式
SAX的工作原理简单地说就是对文档进行顺序扫描,当扫描到文档(document)开始与结束、元素(element)开始与结束、等地方时通知事件处理函数,由事件处理函数做相应动作,然后继续同样的扫描,直至文档结束。
所以有两个关键点:顺序扫描,事件处理函数
3.2 案例:解析指定文件(标签无属性),并将文件中的信息存放到list中。
]>
张三
19
man
李四
20
man
王五
25
woman
3.2.2 解析指定文件(根标签有属性),并将文件中的信息存放到list中
package cmo.qfedu;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
/**
* sax 解析
* @ClassName SaxTest
* @Author ykx
* @Date 2022/8/31 22:10
* @Version 1.0
*/
public class SaxTest {
public static void main(String[] args) throws Exception {
//1.创建解析器工厂
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
//2.通过解析器工厂对象调用方法
SAXParser saxParser = saxParserFactory.newSAXParser();
//3.创建处理器
MyHandler myHandler = new MyHandler();
//4.用解析器对象调用解析方法
saxParser.parse("src/students.xml",myHandler);
for (Student student : myHandler.students) {
System.out.println(student);
}
}
}
MyHandler.java
package cmo.qfedu;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import java.util.ArrayList;
import java.util.List;
/**
* @ClassName MyHandler
* @Author ykx
* @Date 2022/8/31 22:38
* @Version 1.0
*/
public class MyHandler extends DefaultHandler {
ArrayList students;
Student student;
/**
* 当前正在解析的标签名
*/
String tag;
/**
* 重写父类中开始解析文档的方法
* @throws SAXException
*/
@Override
public void startDocument() throws SAXException {
students = new ArrayList<>();
}
/**
* 重写父类中开始解析标签的方法
* @throws SAXException
*/
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
tag=qName;
if ("student".equals(tag)) {
student = new Student();
int count = attributes.getLength();
for (int i = 0; i < count; i++) {
if ("sid".equals(attributes.getQName(i))) {
student.setSid(attributes.getValue(i));
}
}
}
}
/**
* 重写父类中解析标签内容的方法
* @param ch
* @param start
* @param length
* @throws SAXException
*/
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
if ("sname".equals(tag)){
student.setSname(new String(ch,start,length));
}else if ("sage".equals(tag)){
student.setSage(Integer.parseInt(new String(ch,start,length)));
}else if ("ssex".equals(tag)){
student.setSsex(new String(ch,start,length));
}
}
/**
* 重写父类中结束解析标签的方法
* @throws SAXException
*/
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if ("student".equals(qName)){
students.add(student);
}
}
/**
* 重写父类中结束解析文档的方法
* @throws SAXException
*/
@Override
public void endDocument() throws SAXException {
System.out.println("文档解析完成");
}
}
运行结果:
文档解析完成
Student{sid='100', sname='张三', sage=19, ssex='man'}
Student{sid='101', sname='李四', sage=20, ssex='man'}
Student{sid='102', sname='王五', sage=25, ssex='woman'}
Process finished with exit code 0
四、pull解析
pull解析器的方式,和sax解析一样,也是采用事件驱动进行解析的,在eclipse程序中没有内置的支持pull解析的jar包,所以我们需要添加第三方的jar包来支持pull。
案例:解析XML文件(不带属性)
需要准备jar包:kxml2-2.2.2.jar
package cmo.qfedu;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserFactory;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.List;
/**
* @ClassName PullTest
* @Author ykx
* @Date 2022/9/1 0:32
* @Version 1.0
*/
public class PullTest {
public static void main(String[] args) throws Exception {
//创建pull解析器工厂对象
XmlPullParserFactory xmlPullParserFactory = XmlPullParserFactory.newInstance();
//创建pull解析器
XmlPullParser xmlPullParser = xmlPullParserFactory.newPullParser();
//指定数据源,解析students.xml
xmlPullParser.setInput(new FileReader("src/students.xml"));
//获取其状态码,区分现在是哪个事件源(文档开头,文档结尾,标签开头,标签结尾)
int eventType = xmlPullParser.getEventType();
List studentList = new ArrayList<>();
Student student = null;
//循环解析,直至文件解析结束
while (eventType!=XmlPullParser.END_DOCUMENT){
//获取标签名称
String name = xmlPullParser.getName();
if (eventType==XmlPullParser.START_DOCUMENT){
System.out.println("开始解析文档");
}else if (eventType==XmlPullParser.START_TAG){
switch (name){
case "student":
student = new Student();
int count = xmlPullParser.getAttributeCount();
for (int i = 0; i < count; i++) {
String attributeName = xmlPullParser.getAttributeName(i);
String attributeValue = xmlPullParser.getAttributeValue(i);
if ("sid".equals(attributeName)){
student.setSid(attributeValue);
}
}
break;
case "sname":
//**获取标签的文本内容**
student.setSname(xmlPullParser.nextText());
break;
case "sage":
student.setSage(Integer.parseInt(xmlPullParser.nextText()));
break;
case "ssex":
student.setSsex(xmlPullParser.nextText());
break;
}
}else if (eventType==XmlPullParser.END_TAG){
if ("student".equals(name)){
studentList.add(student);
}
}
//让指针继续往下解析下一个事件源
eventType = xmlPullParser.next();
}
for (Student student1 : studentList) {
System.out.println(student1);
}
}
}
PULL vs SAX
Pull解析器和SAX解析器虽有相似性但也有区别,他们的区别为: