前言:
XML解析工具
DOM解析原理:
1)JAXP (oracle-Sun公司官方)
2)JDOM工具(非官方)
3)Dom4J工具(非官方)
三大框架(默认读取xml的工具就是Dom4j)
.......
SAX解析原理:
1)Sax解析工具(oracle-sun公司官方)
老样子,三个问题:
SAX解析是什么?
SAX怎么用?
SAX运用场景?
SAX是什么?
也是用来解析XML的
SAX解析工具- 内置在jdk中。org.xml.sax.*
SAX运用场景?
DOM解析原理:一次性把xml文档加载进内存,然后在内存中构建Document树。
对内存要求比较要。
缺点: 不适合读取大容量的xml文件,容易导致内存溢出。
SAX解析原理: 加载一点,读取一点,处理一点。对内存要求比较低。
SAX解析工具核心:
核心的API:
SAXParser类: 用于读取和解析xml文件对象
parse(File f, DefaultHandler dh)方法: 解析xml文件
参数一: File:表示 读取的xml文件。
参数二: DefaultHandler: SAX事件处理程序。使用DefaultHandler的子类
第一步:创建对象
//1.创建SAXParser对象
SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
//2.调用parse方法
/**
* 参数一: xml文档
* 参数二: DefaultHandler的子类 MyDefaultHandler()为自定义
*/
parser.parse(new File(".\\src\\Go\\person.xml"),
new MyDefaultHandler());
注意:
这里创建SAXParser对象 不能直接通过构造函数来创造,因为用到了单例工厂模式。
链接:类 SAXParser的jdk文档
所以创建一个SAXParser对象 需要:SAXParserFactory.newInstance().newSAXParser();
DefaultHandler类的API:后三个最重要
- void startDocument() : 在读到文档开始时调用
- void endDocument() :在读到文档结束时调用
- void startElement(String uri, String localName, String qName, Attributes attributes) :
读到开始标签时调用 - void endElement(String uri, String localName, String qName) :读到结束标签时调用
- void characters(char[] ch, int start, int length) : 读到文本内容时调用
第二步:自定义类继承DefaultHandler重写方法
这些都是要重写的 举个例子:
public class MyDefaultHandler extends DefaultHandler {
/**
* 开始文档时调用
*/
@Override
public void startDocument() throws SAXException {
System.out.println("MyDefaultHandler.startDocument()");
}
/**
* 开始标签时调用
* @param qName: 表示开始标签的标签名
* @param attributes: 表示开始标签内包含的属性列表
*/
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
System.out.println("MyDefaultHandler.startElement()-->"+qName);
}
/**
* 结束标签时调用
* @param qName: 结束标签的标签名称
*/
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
System.out.println("MyDefaultHandler.endElement()-->"+qName);
}
/**
* 读到文本内容的时调用
* @param ch: 表示当前读完的所有文本内容
* @param start: 表示当前文本内容的开始位置
* @param length: 表示当前文本内容的长度
* char[]( 张三 20) 100
* 98 2
*/
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
//得到当前文本内容
String content = new String(ch,start,length);
System.out.println("MyDefaultHandler.characters()-->"+content);
}
/**
* 结束文档时调用
*/
@Override
public void endDocument() throws SAXException {
System.out.println("MyDefaultHandler.endDocument()");
}
}
xml样例:
<?xml version="1.0" encoding="utf-8"?>
<contactList>
<contact id="001" name="eric">
<name>张三</name>
<age>20</age>
<phone>134222223333</phone>
<email>zhangsan@qq.com</email>
<qq>432221111</qq>
</contact>
<contact id="002" name="jacky">
<name>eric</name>
<age>20</age>
<phone>134222225555</phone>
<email>lisi@qq.com</email>
<qq>432222222</qq>
</contact>
</contactList>
结果:
MyDefaultHandler.startDocument()
MyDefaultHandler.startElement()-->contactList
MyDefaultHandler.characters()-->
MyDefaultHandler.startElement()-->contact
MyDefaultHandler.characters()-->
MyDefaultHandler.startElement()-->name
MyDefaultHandler.characters()-->张三
MyDefaultHandler.endElement()-->name
MyDefaultHandler.characters()-->
MyDefaultHandler.startElement()-->age
MyDefaultHandler.characters()-->20
MyDefaultHandler.endElement()-->age
MyDefaultHandler.characters()-->
MyDefaultHandler.startElement()-->phone
MyDefaultHandler.characters()-->134222223333
MyDefaultHandler.endElement()-->phone
MyDefaultHandler.characters()-->
MyDefaultHandler.startElement()-->email
MyDefaultHandler.characters()-->zhangsan@qq.com
MyDefaultHandler.endElement()-->email
MyDefaultHandler.characters()-->
MyDefaultHandler.startElement()-->qq
MyDefaultHandler.characters()-->432221111
MyDefaultHandler.endElement()-->qq
MyDefaultHandler.characters()-->
MyDefaultHandler.endElement()-->contact
MyDefaultHandler.characters()-->
MyDefaultHandler.startElement()-->contact
MyDefaultHandler.characters()-->
MyDefaultHandler.startElement()-->name
MyDefaultHandler.characters()-->eric
MyDefaultHandler.endElement()-->name
MyDefaultHandler.characters()-->
MyDefaultHandler.startElement()-->age
MyDefaultHandler.characters()-->20
MyDefaultHandler.endElement()-->age
MyDefaultHandler.characters()-->
MyDefaultHandler.startElement()-->phone
MyDefaultHandler.characters()-->134222225555
MyDefaultHandler.endElement()-->phone
MyDefaultHandler.characters()-->
MyDefaultHandler.startElement()-->email
MyDefaultHandler.characters()-->lisi@qq.com
MyDefaultHandler.endElement()-->email
MyDefaultHandler.characters()-->
MyDefaultHandler.startElement()-->qq
MyDefaultHandler.characters()-->432222222
MyDefaultHandler.endElement()-->qq
MyDefaultHandler.characters()-->
MyDefaultHandler.endElement()-->contact
MyDefaultHandler.characters()-->
MyDefaultHandler.endElement()-->contactList
MyDefaultHandler.endDocument()
注意:
问题:MyDefaultHandler.characters()-->空白 ?
答:
<contactList>
<contact>
之间也是有文本的 是换行和空格 被characters方法读取了。
来看一下SAX解析XML的流程图:(图片来自传智播客)
回到开头SAX解析原理: 加载一点,读取一点,处理一点。对内存要求比较低。
总结:
==================DOM解析 vs SAX解析 ============================
DOM解析 :
原理: 一次性加载xml文档,不适合大容量的文件读取
DOM解析可以任意进行增删改成
DOM解析任意读取任何位置的数据,甚至往回读
DOM解析面向对象的编程方法(Node,Element,Attribute),
Java开发者编码比较简单。
SAX解析 :
原理: 加载一点,读取一点,处理一点。适合大容量文件的读取
SAX解析只能读取
SAX解析只能从上往下,按顺序读取,不能往回读
SAX解析基于事件的编程方法。java开发编码相对复杂。
XML操作:
1)Dom4j修改xml文档
new XMLWrier();
......
2)xPath技术: 快速查询xml节点
selectNodes()
selectSinglNode();
3) SAX解析
SAXParser parse
parser()
DefaultHandler类:
startElement();
characters();
endElement();